[Pkg-golang-commits] [golang] 26/27: Imported Debian patch 2:1.6-0ubuntu2
Michael Hudson-Doyle
mwhudson-guest at moszumanska.debian.org
Tue Mar 1 02:57:46 UTC 2016
This is an automated email from the git hooks/post-receive script.
mwhudson-guest pushed a commit to branch gbp
in repository golang.
commit cc375595d4bf6447fd24f363651c5c80e99e1017
Author: Matthias Klose <doko at ubuntu.com>
Date: Sun Feb 21 16:50:57 2016 +0100
Imported Debian patch 2:1.6-0ubuntu2
---
debian/changelog | 6 +
debian/patches/0001-s390x-port.patch | 14009 ++++++++++++++++++++++++++++++---
2 files changed, 12778 insertions(+), 1237 deletions(-)
diff --git a/debian/changelog b/debian/changelog
index 4f7d40d..23d7274 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+golang (2:1.6-0ubuntu2) xenial; urgency=medium
+
+ * Update d/patches/0001-s390x-port.patch from IBM's repo.
+
+ -- Matthias Klose <doko at ubuntu.com> Sun, 21 Feb 2016 16:50:57 +0100
+
golang (2:1.6-0ubuntu1) xenial; urgency=medium
* Go 1.6 release.
diff --git a/debian/patches/0001-s390x-port.patch b/debian/patches/0001-s390x-port.patch
index 4d64ffc..6e8e4b3 100644
--- a/debian/patches/0001-s390x-port.patch
+++ b/debian/patches/0001-s390x-port.patch
@@ -1,204 +1,13 @@
-From 8cafcab0d9460c1fb9c6b05f338f75fb90d00fad Mon Sep 17 00:00:00 2001
-From: wgo <billo at ca.ibm.com>
-Date: Sun, 12 Jul 2015 23:28:19 -0400
Subject: [PATCH] [s390x] Add support for Linux on IBM z architecture (s390x)
-Change-Id: I684a4007d8e4bd2d42cad6ba97b0938031a48458
----
- api/go1.6.txt | 9279 ++++++++++++++++++++
- misc/cgo/test/issue9400/asm_s390x.s | 31 +
- src/cmd/api/goapi.go | 2 +
- src/cmd/asm/internal/arch/arch.go | 55 +
- src/cmd/asm/internal/arch/s390x.go | 116 +
- src/cmd/asm/internal/asm/asm.go | 23 +
- src/cmd/cgo/main.go | 2 +-
- src/cmd/cgo/out.go | 1 +
- src/cmd/compile/internal/gc/cgen.go | 14 +-
- src/cmd/compile/internal/gc/go.go | 6 +
- src/cmd/compile/internal/gc/gsubr.go | 6 +-
- src/cmd/compile/internal/gc/lex.go | 8 +-
- src/cmd/compile/internal/gc/pgen.go | 4 +-
- src/cmd/compile/internal/gc/reg.go | 6 +-
- src/cmd/compile/internal/gc/walk.go | 4 +-
- src/cmd/compile/internal/s390x/cgen.go | 178 +
- src/cmd/compile/internal/s390x/galign.go | 95 +
- src/cmd/compile/internal/s390x/ggen.go | 611 ++
- src/cmd/compile/internal/s390x/gsubr.go | 972 ++
- src/cmd/compile/internal/s390x/peep.go | 1419 +++
- src/cmd/compile/internal/s390x/prog.go | 183 +
- src/cmd/compile/internal/s390x/reg.go | 131 +
- src/cmd/compile/main.go | 3 +
- src/cmd/dist/build.go | 1 +
- src/cmd/dist/buildtool.go | 3 +
- src/cmd/dist/test.go | 4 +-
- src/cmd/dist/util.go | 2 +
- src/cmd/go/build.go | 8 +-
- src/cmd/internal/obj/link.go | 3 +
- src/cmd/internal/obj/s390x/a.out.go | 360 +
- src/cmd/internal/obj/s390x/anames.go | 152 +
- src/cmd/internal/obj/s390x/anamesz.go | 35 +
- src/cmd/internal/obj/s390x/asmz.go | 4017 +++++++++
- src/cmd/internal/obj/s390x/listz.go | 70 +
- src/cmd/internal/obj/s390x/objz.go | 990 +++
- src/cmd/internal/obj/util.go | 2 +
- src/cmd/internal/objfile/disasm.go | 1 +
- src/cmd/internal/objfile/elf.go | 2 +
- src/cmd/link/internal/ld/arch.go | 9 +
- src/cmd/link/internal/ld/data.go | 47 +-
- src/cmd/link/internal/ld/dwarf.go | 37 +-
- src/cmd/link/internal/ld/elf.go | 120 +-
- src/cmd/link/internal/ld/ldelf.go | 45 +-
- src/cmd/link/internal/ld/lib.go | 2 +-
- src/cmd/link/internal/ld/link.go | 1 +
- src/cmd/link/internal/ld/symtab.go | 3 +-
- src/cmd/link/internal/s390x/asm.go | 643 ++
- src/cmd/link/internal/s390x/l.go | 78 +
- src/cmd/link/internal/s390x/obj.go | 115 +
- src/cmd/link/main.go | 3 +
- src/cmd/objdump/objdump_test.go | 4 +
- src/cmd/vet/asmdecl.go | 2 +
- src/crypto/aes/asm_s390x.s | 97 +
- src/crypto/aes/cipher_asm.go | 2 +-
- src/crypto/aes/cipher_generic.go | 10 +-
- src/crypto/aes/gcm_generic.go | 15 +
- src/crypto/cipher/xor.go | 2 +-
- src/crypto/sha1/sha1block_decl.go | 2 +-
- src/crypto/sha1/sha1block_generic.go | 2 +-
- src/crypto/sha1/sha1block_s390x.s | 37 +
- src/crypto/sha256/sha256block.go | 2 +-
- src/crypto/sha256/sha256block_decl.go | 2 +-
- src/crypto/sha256/sha256block_generic.go | 9 +
- src/crypto/sha256/sha256block_s390x.s | 37 +
- src/crypto/sha512/sha512block.go | 2 +-
- src/crypto/sha512/sha512block_decl.go | 2 +-
- src/crypto/sha512/sha512block_generic.go | 9 +
- src/crypto/sha512/sha512block_s390x.s | 37 +
- src/crypto/x509/sec1.go | 8 +-
- src/crypto/x509/sec1_test.go | 4 +-
- src/debug/elf/elf.go | 66 +
- src/debug/elf/file.go | 51 +
- src/debug/gosym/pclntab.go | 2 +-
- src/go/build/build.go | 1 +
- src/hash/crc32/crc32_generic.go | 2 +-
- src/internal/syscall/unix/getrandom_linux_s390x.go | 7 +
- src/math/big/arith_s390x.s | 574 ++
- src/math/dim_s390x.s | 132 +
- src/math/sqrt_s390x.s | 12 +
- src/math/stubs_s390x.s | 77 +
- src/net/http/fs_test.go | 6 +-
- src/net/lookup_test.go | 5 +
- src/reflect/asm_s390x.s | 30 +
- src/runtime/asm_s390x.s | 1182 +++
- src/runtime/cgo/asm_s390x.s | 56 +
- src/runtime/cgo/gcc_linux_s390x.c | 68 +
- src/runtime/cgo/gcc_s390x.S | 43 +
- src/runtime/cgocall.go | 6 +-
- src/runtime/defs_linux_s390x.go | 176 +
- src/runtime/extern.go | 2 +-
- src/runtime/gcinfo_test.go | 2 +-
- src/runtime/hash64.go | 2 +-
- src/runtime/internal/atomic/asm_s390x.s | 192 +
- src/runtime/internal/atomic/atomic_s390x.go | 63 +
- src/runtime/internal/sys/arch_s390x.go | 18 +
- src/runtime/internal/sys/zgoarch_s390x.go | 26 +
- src/runtime/lfstack_linux_s390x.go | 25 +
- src/runtime/memclr_s390x.s | 122 +
- src/runtime/memmove_s390x.s | 189 +
- src/runtime/noasm.go | 2 +-
- src/runtime/os1_linux_generic.go | 1 +
- src/runtime/os1_linux_s390x.go | 29 +
- src/runtime/os2_linux_generic.go | 1 +
- src/runtime/os2_linux_s390x.go | 22 +
- src/runtime/rt0_linux_s390x.s | 20 +
- src/runtime/runtime-gdb_test.go | 2 +-
- src/runtime/signal_linux_s390x.go | 50 +
- src/runtime/signal_s390x.go | 170 +
- src/runtime/sys_linux_s390x.s | 437 +
- src/runtime/sys_s390x.go | 48 +
- src/runtime/tls_s390x.s | 51 +
- src/runtime/unaligned1.go | 2 +-
- src/sync/atomic/asm_s390x.s | 149 +
- src/syscall/asm_linux_s390x.s | 173 +
- src/syscall/exec_linux.go | 7 +-
- src/syscall/mkall.sh | 7 +
- src/syscall/syscall_linux_s390x.go | 296 +
- src/syscall/types_linux.go | 18 +
- src/syscall/zerrors_linux_s390x.go | 1869 ++++
- src/syscall/zsyscall_linux_s390x.go | 1578 ++++
- src/syscall/zsysnum_linux_s390x.go | 293 +
- src/syscall/ztypes_linux_s390x.go | 623 ++
- test/fixedbugs/issue11656.go | 2 +
- test/init1.go | 2 +-
- test/nilptr3.go | 3 +-
- test/nosplit.go | 3 +
- 126 files changed, 29072 insertions(+), 110 deletions(-)
- create mode 100644 misc/cgo/test/issue9400/asm_s390x.s
- create mode 100644 src/cmd/asm/internal/arch/s390x.go
- create mode 100644 src/cmd/compile/internal/s390x/cgen.go
- create mode 100644 src/cmd/compile/internal/s390x/galign.go
- create mode 100644 src/cmd/compile/internal/s390x/ggen.go
- create mode 100644 src/cmd/compile/internal/s390x/gsubr.go
- create mode 100644 src/cmd/compile/internal/s390x/peep.go
- create mode 100644 src/cmd/compile/internal/s390x/prog.go
- create mode 100644 src/cmd/compile/internal/s390x/reg.go
- create mode 100644 src/cmd/internal/obj/s390x/a.out.go
- create mode 100644 src/cmd/internal/obj/s390x/anames.go
- create mode 100644 src/cmd/internal/obj/s390x/anamesz.go
- create mode 100644 src/cmd/internal/obj/s390x/asmz.go
- create mode 100644 src/cmd/internal/obj/s390x/listz.go
- create mode 100644 src/cmd/internal/obj/s390x/objz.go
- create mode 100644 src/cmd/link/internal/s390x/asm.go
- create mode 100644 src/cmd/link/internal/s390x/l.go
- create mode 100644 src/cmd/link/internal/s390x/obj.go
- create mode 100644 src/crypto/aes/asm_s390x.s
- create mode 100644 src/crypto/aes/gcm_generic.go
- create mode 100644 src/crypto/sha1/sha1block_s390x.s
- create mode 100644 src/crypto/sha256/sha256block_generic.go
- create mode 100644 src/crypto/sha256/sha256block_s390x.s
- create mode 100644 src/crypto/sha512/sha512block_generic.go
- create mode 100644 src/crypto/sha512/sha512block_s390x.s
- create mode 100644 src/internal/syscall/unix/getrandom_linux_s390x.go
- create mode 100644 src/math/big/arith_s390x.s
- create mode 100644 src/math/dim_s390x.s
- create mode 100644 src/math/sqrt_s390x.s
- create mode 100644 src/math/stubs_s390x.s
- create mode 100644 src/reflect/asm_s390x.s
- create mode 100644 src/runtime/asm_s390x.s
- create mode 100644 src/runtime/cgo/asm_s390x.s
- create mode 100644 src/runtime/cgo/gcc_linux_s390x.c
- create mode 100644 src/runtime/cgo/gcc_s390x.S
- create mode 100644 src/runtime/defs_linux_s390x.go
- create mode 100644 src/runtime/internal/atomic/asm_s390x.s
- create mode 100644 src/runtime/internal/atomic/atomic_s390x.go
- create mode 100644 src/runtime/internal/sys/arch_s390x.go
- create mode 100644 src/runtime/internal/sys/zgoarch_s390x.go
- create mode 100644 src/runtime/lfstack_linux_s390x.go
- create mode 100644 src/runtime/memclr_s390x.s
- create mode 100644 src/runtime/memmove_s390x.s
- create mode 100644 src/runtime/os1_linux_s390x.go
- create mode 100644 src/runtime/os2_linux_s390x.go
- create mode 100644 src/runtime/rt0_linux_s390x.s
- create mode 100644 src/runtime/signal_linux_s390x.go
- create mode 100644 src/runtime/signal_s390x.go
- create mode 100644 src/runtime/sys_linux_s390x.s
- create mode 100644 src/runtime/sys_s390x.go
- create mode 100644 src/runtime/tls_s390x.s
- create mode 100644 src/sync/atomic/asm_s390x.s
- create mode 100644 src/syscall/asm_linux_s390x.s
- create mode 100644 src/syscall/syscall_linux_s390x.go
- create mode 100644 src/syscall/zerrors_linux_s390x.go
- create mode 100644 src/syscall/zsyscall_linux_s390x.go
- create mode 100644 src/syscall/zsysnum_linux_s390x.go
- create mode 100644 src/syscall/ztypes_linux_s390x.go
+https://github.com/linux-on-ibm-z/go/tree/release-branch.go1.6
+git diff bfccf7b3..HEAD
-diff --git a/api/go1.6.txt b/api/go1.6.txt
-index d63efd0..6261e9c 100644
---- a/api/go1.6.txt
-+++ b/api/go1.6.txt
-@@ -273,3 +273,9282 @@ pkg text/template, method (ExecError) Error() string
- pkg text/template, type ExecError struct
- pkg text/template, type ExecError struct, Err error
- pkg text/template, type ExecError struct, Name string
+diff --git a/api/next.txt b/api/next.txt
+index e69de29..ec1c52c 100644
+--- a/api/next.txt
++++ b/api/next.txt
+@@ -0,0 +1,9371 @@
+pkg debug/elf, const R_390_12 = 2
+pkg debug/elf, const R_390_12 R_S390X
+pkg debug/elf, const R_390_16 = 3
@@ -465,7 +274,7 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x-cgo), const AF_LLC ideal-int
+pkg syscall (linux-s390x-cgo), const AF_LOCAL = 1
+pkg syscall (linux-s390x-cgo), const AF_LOCAL ideal-int
-+pkg syscall (linux-s390x-cgo), const AF_MAX = 40
++pkg syscall (linux-s390x-cgo), const AF_MAX = 41
+pkg syscall (linux-s390x-cgo), const AF_MAX ideal-int
+pkg syscall (linux-s390x-cgo), const AF_NETBEUI = 13
+pkg syscall (linux-s390x-cgo), const AF_NETBEUI ideal-int
@@ -495,6 +304,8 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x-cgo), const AF_SNA ideal-int
+pkg syscall (linux-s390x-cgo), const AF_TIPC = 30
+pkg syscall (linux-s390x-cgo), const AF_TIPC ideal-int
++pkg syscall (linux-s390x-cgo), const AF_VSOCK = 40
++pkg syscall (linux-s390x-cgo), const AF_VSOCK ideal-int
+pkg syscall (linux-s390x-cgo), const AF_WANPIPE = 25
+pkg syscall (linux-s390x-cgo), const AF_WANPIPE ideal-int
+pkg syscall (linux-s390x-cgo), const AF_X25 = 9
@@ -1059,8 +870,6 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x-cgo), const EPOLLIN ideal-int
+pkg syscall (linux-s390x-cgo), const EPOLLMSG = 1024
+pkg syscall (linux-s390x-cgo), const EPOLLMSG ideal-int
-+pkg syscall (linux-s390x-cgo), const EPOLL_NONBLOCK = 2048
-+pkg syscall (linux-s390x-cgo), const EPOLL_NONBLOCK ideal-int
+pkg syscall (linux-s390x-cgo), const EPOLLONESHOT = 1073741824
+pkg syscall (linux-s390x-cgo), const EPOLLONESHOT ideal-int
+pkg syscall (linux-s390x-cgo), const EPOLLOUT = 4
@@ -1111,8 +920,6 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x-cgo), const ETH_P_8021AH ideal-int
+pkg syscall (linux-s390x-cgo), const ETH_P_8021Q = 33024
+pkg syscall (linux-s390x-cgo), const ETH_P_8021Q ideal-int
-+pkg syscall (linux-s390x-cgo), const ETH_P_80221 = 35095
-+pkg syscall (linux-s390x-cgo), const ETH_P_80221 ideal-int
+pkg syscall (linux-s390x-cgo), const ETH_P_802_2 = 4
+pkg syscall (linux-s390x-cgo), const ETH_P_802_2 ideal-int
+pkg syscall (linux-s390x-cgo), const ETH_P_802_3 = 1
@@ -1373,12 +1180,8 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x-cgo), const IFA_F_DEPRECATED ideal-int
+pkg syscall (linux-s390x-cgo), const IFA_F_HOMEADDRESS = 16
+pkg syscall (linux-s390x-cgo), const IFA_F_HOMEADDRESS ideal-int
-+pkg syscall (linux-s390x-cgo), const IFA_F_MANAGETEMPADDR = 256
-+pkg syscall (linux-s390x-cgo), const IFA_F_MANAGETEMPADDR ideal-int
+pkg syscall (linux-s390x-cgo), const IFA_F_NODAD = 2
+pkg syscall (linux-s390x-cgo), const IFA_F_NODAD ideal-int
-+pkg syscall (linux-s390x-cgo), const IFA_F_NOPREFIXROUTE = 512
-+pkg syscall (linux-s390x-cgo), const IFA_F_NOPREFIXROUTE ideal-int
+pkg syscall (linux-s390x-cgo), const IFA_F_OPTIMISTIC = 4
+pkg syscall (linux-s390x-cgo), const IFA_F_OPTIMISTIC ideal-int
+pkg syscall (linux-s390x-cgo), const IFA_F_PERMANENT = 128
@@ -1393,7 +1196,7 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x-cgo), const IFA_LABEL ideal-int
+pkg syscall (linux-s390x-cgo), const IFA_LOCAL = 2
+pkg syscall (linux-s390x-cgo), const IFA_LOCAL ideal-int
-+pkg syscall (linux-s390x-cgo), const IFA_MAX = 8
++pkg syscall (linux-s390x-cgo), const IFA_MAX = 7
+pkg syscall (linux-s390x-cgo), const IFA_MAX ideal-int
+pkg syscall (linux-s390x-cgo), const IFA_MULTICAST = 7
+pkg syscall (linux-s390x-cgo), const IFA_MULTICAST ideal-int
@@ -1449,6 +1252,8 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x-cgo), const IFF_MULTI_QUEUE ideal-int
+pkg syscall (linux-s390x-cgo), const IFF_NOARP = 128
+pkg syscall (linux-s390x-cgo), const IFF_NOARP ideal-int
++pkg syscall (linux-s390x-cgo), const IFF_NOFILTER = 4096
++pkg syscall (linux-s390x-cgo), const IFF_NOFILTER ideal-int
+pkg syscall (linux-s390x-cgo), const IFF_NO_PI = 4096
+pkg syscall (linux-s390x-cgo), const IFF_NO_PI ideal-int
+pkg syscall (linux-s390x-cgo), const IFF_NOTRAILERS = 32
@@ -1457,6 +1262,8 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x-cgo), const IFF_ONE_QUEUE ideal-int
+pkg syscall (linux-s390x-cgo), const IFF_OVS_DATAPATH = 32768
+pkg syscall (linux-s390x-cgo), const IFF_OVS_DATAPATH ideal-int
++pkg syscall (linux-s390x-cgo), const IFF_PERSIST = 2048
++pkg syscall (linux-s390x-cgo), const IFF_PERSIST ideal-int
+pkg syscall (linux-s390x-cgo), const IFF_POINTOPOINT = 16
+pkg syscall (linux-s390x-cgo), const IFF_POINTOPOINT ideal-int
+pkg syscall (linux-s390x-cgo), const IFF_PORTSEL = 8192
@@ -1693,6 +1500,8 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x-cgo), const IP_PMTUDISC_WANT ideal-int
+pkg syscall (linux-s390x-cgo), const IPPROTO_AH = 51
+pkg syscall (linux-s390x-cgo), const IPPROTO_AH ideal-int
++pkg syscall (linux-s390x-cgo), const IPPROTO_BEETPH = 94
++pkg syscall (linux-s390x-cgo), const IPPROTO_BEETPH ideal-int
+pkg syscall (linux-s390x-cgo), const IPPROTO_COMP = 108
+pkg syscall (linux-s390x-cgo), const IPPROTO_COMP ideal-int
+pkg syscall (linux-s390x-cgo), const IPPROTO_DCCP = 33
@@ -1721,6 +1530,8 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x-cgo), const IPPROTO_IGMP ideal-int
+pkg syscall (linux-s390x-cgo), const IPPROTO_IPIP = 4
+pkg syscall (linux-s390x-cgo), const IPPROTO_IPIP ideal-int
++pkg syscall (linux-s390x-cgo), const IPPROTO_MH = 135
++pkg syscall (linux-s390x-cgo), const IPPROTO_MH ideal-int
+pkg syscall (linux-s390x-cgo), const IPPROTO_MTP = 92
+pkg syscall (linux-s390x-cgo), const IPPROTO_MTP ideal-int
+pkg syscall (linux-s390x-cgo), const IPPROTO_NONE = 59
@@ -1946,8 +1757,10 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x-cgo), const MAP_FIXED ideal-int
+pkg syscall (linux-s390x-cgo), const MAP_GROWSDOWN = 256
+pkg syscall (linux-s390x-cgo), const MAP_GROWSDOWN ideal-int
-+pkg syscall (linux-s390x-cgo), const MAP_GROWSUP = 512
-+pkg syscall (linux-s390x-cgo), const MAP_GROWSUP ideal-int
++pkg syscall (linux-s390x-cgo), const MAP_HUGE_MASK = 63
++pkg syscall (linux-s390x-cgo), const MAP_HUGE_MASK ideal-int
++pkg syscall (linux-s390x-cgo), const MAP_HUGE_SHIFT = 26
++pkg syscall (linux-s390x-cgo), const MAP_HUGE_SHIFT ideal-int
+pkg syscall (linux-s390x-cgo), const MAP_HUGETLB = 262144
+pkg syscall (linux-s390x-cgo), const MAP_HUGETLB ideal-int
+pkg syscall (linux-s390x-cgo), const MAP_LOCKED = 8192
@@ -2234,6 +2047,8 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x-cgo), const O_RSYNC = 1052672
+pkg syscall (linux-s390x-cgo), const O_RSYNC ideal-int
+pkg syscall (linux-s390x-cgo), const O_SYNC = 1052672
++pkg syscall (linux-s390x-cgo), const O_TMPFILE = 4259840
++pkg syscall (linux-s390x-cgo), const O_TMPFILE ideal-int
+pkg syscall (linux-s390x-cgo), const O_TRUNC = 512
+pkg syscall (linux-s390x-cgo), const PACKET_ADD_MEMBERSHIP = 1
+pkg syscall (linux-s390x-cgo), const PACKET_ADD_MEMBERSHIP ideal-int
@@ -2389,8 +2204,6 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x-cgo), const PR_GET_SECCOMP ideal-int
+pkg syscall (linux-s390x-cgo), const PR_GET_SECUREBITS = 27
+pkg syscall (linux-s390x-cgo), const PR_GET_SECUREBITS ideal-int
-+pkg syscall (linux-s390x-cgo), const PR_GET_THP_DISABLE = 42
-+pkg syscall (linux-s390x-cgo), const PR_GET_THP_DISABLE ideal-int
+pkg syscall (linux-s390x-cgo), const PR_GET_TID_ADDRESS = 40
+pkg syscall (linux-s390x-cgo), const PR_GET_TID_ADDRESS ideal-int
+pkg syscall (linux-s390x-cgo), const PR_GET_TIMERSLACK = 30
@@ -2487,8 +2300,6 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x-cgo), const PR_SET_SECCOMP ideal-int
+pkg syscall (linux-s390x-cgo), const PR_SET_SECUREBITS = 28
+pkg syscall (linux-s390x-cgo), const PR_SET_SECUREBITS ideal-int
-+pkg syscall (linux-s390x-cgo), const PR_SET_THP_DISABLE = 41
-+pkg syscall (linux-s390x-cgo), const PR_SET_THP_DISABLE ideal-int
+pkg syscall (linux-s390x-cgo), const PR_SET_TIMERSLACK = 29
+pkg syscall (linux-s390x-cgo), const PR_SET_TIMERSLACK ideal-int
+pkg syscall (linux-s390x-cgo), const PR_SET_TIMING = 14
@@ -2665,6 +2476,8 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x-cgo), const PTRACE_GETREGS ideal-int
+pkg syscall (linux-s390x-cgo), const PTRACE_GETSIGINFO = 16898
+pkg syscall (linux-s390x-cgo), const PTRACE_GETSIGINFO ideal-int
++pkg syscall (linux-s390x-cgo), const PTRACE_GETSIGMASK = 16906
++pkg syscall (linux-s390x-cgo), const PTRACE_GETSIGMASK ideal-int
+pkg syscall (linux-s390x-cgo), const PTRACE_INTERRUPT = 16903
+pkg syscall (linux-s390x-cgo), const PTRACE_INTERRUPT ideal-int
+pkg syscall (linux-s390x-cgo), const PTRACE_KILL = 8
@@ -2737,10 +2550,14 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x-cgo), const PTRACE_SETREGS ideal-int
+pkg syscall (linux-s390x-cgo), const PTRACE_SETSIGINFO = 16899
+pkg syscall (linux-s390x-cgo), const PTRACE_SETSIGINFO ideal-int
++pkg syscall (linux-s390x-cgo), const PTRACE_SETSIGMASK = 16907
++pkg syscall (linux-s390x-cgo), const PTRACE_SETSIGMASK ideal-int
+pkg syscall (linux-s390x-cgo), const PTRACE_SINGLESTEP = 9
+pkg syscall (linux-s390x-cgo), const PTRACE_SINGLESTEP ideal-int
+pkg syscall (linux-s390x-cgo), const PTRACE_SYSCALL = 24
+pkg syscall (linux-s390x-cgo), const PTRACE_SYSCALL ideal-int
++pkg syscall (linux-s390x-cgo), const PTRACE_TE_ABORT_RAND = 20497
++pkg syscall (linux-s390x-cgo), const PTRACE_TE_ABORT_RAND ideal-int
+pkg syscall (linux-s390x-cgo), const PTRACE_TRACEME = 0
+pkg syscall (linux-s390x-cgo), const PTRACE_TRACEME ideal-int
+pkg syscall (linux-s390x-cgo), const RLIM_INFINITY = -1
@@ -2811,7 +2628,7 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x-cgo), const RTAX_INITRWND ideal-int
+pkg syscall (linux-s390x-cgo), const RTAX_LOCK = 1
+pkg syscall (linux-s390x-cgo), const RTAX_LOCK ideal-int
-+pkg syscall (linux-s390x-cgo), const RTAX_MAX = 23
++pkg syscall (linux-s390x-cgo), const RTAX_MAX = 15
+pkg syscall (linux-s390x-cgo), const RTAX_MAX ideal-int
+pkg syscall (linux-s390x-cgo), const RTAX_MTU = 2
+pkg syscall (linux-s390x-cgo), const RTAX_MTU ideal-int
@@ -3409,8 +3226,6 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x-cgo), const SO_ATTACH_FILTER ideal-int
+pkg syscall (linux-s390x-cgo), const SO_BINDTODEVICE = 25
+pkg syscall (linux-s390x-cgo), const SO_BINDTODEVICE ideal-int
-+pkg syscall (linux-s390x-cgo), const SO_BPF_EXTENSIONS = 48
-+pkg syscall (linux-s390x-cgo), const SO_BPF_EXTENSIONS ideal-int
+pkg syscall (linux-s390x-cgo), const SO_BROADCAST = 6
+pkg syscall (linux-s390x-cgo), const SO_BSDCOMPAT = 14
+pkg syscall (linux-s390x-cgo), const SO_BSDCOMPAT ideal-int
@@ -4106,10 +3921,24 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x-cgo), const TCOFLUSH ideal-int
+pkg syscall (linux-s390x-cgo), const TCP_CONGESTION = 13
+pkg syscall (linux-s390x-cgo), const TCP_CONGESTION ideal-int
++pkg syscall (linux-s390x-cgo), const TCP_COOKIE_IN_ALWAYS = 1
++pkg syscall (linux-s390x-cgo), const TCP_COOKIE_IN_ALWAYS ideal-int
++pkg syscall (linux-s390x-cgo), const TCP_COOKIE_MAX = 16
++pkg syscall (linux-s390x-cgo), const TCP_COOKIE_MAX ideal-int
++pkg syscall (linux-s390x-cgo), const TCP_COOKIE_MIN = 8
++pkg syscall (linux-s390x-cgo), const TCP_COOKIE_MIN ideal-int
++pkg syscall (linux-s390x-cgo), const TCP_COOKIE_OUT_NEVER = 2
++pkg syscall (linux-s390x-cgo), const TCP_COOKIE_OUT_NEVER ideal-int
++pkg syscall (linux-s390x-cgo), const TCP_COOKIE_PAIR_SIZE = 32
++pkg syscall (linux-s390x-cgo), const TCP_COOKIE_PAIR_SIZE ideal-int
++pkg syscall (linux-s390x-cgo), const TCP_COOKIE_TRANSACTIONS = 15
++pkg syscall (linux-s390x-cgo), const TCP_COOKIE_TRANSACTIONS ideal-int
+pkg syscall (linux-s390x-cgo), const TCP_CORK = 3
+pkg syscall (linux-s390x-cgo), const TCP_CORK ideal-int
+pkg syscall (linux-s390x-cgo), const TCP_DEFER_ACCEPT = 9
+pkg syscall (linux-s390x-cgo), const TCP_DEFER_ACCEPT ideal-int
++pkg syscall (linux-s390x-cgo), const TCP_FASTOPEN = 23
++pkg syscall (linux-s390x-cgo), const TCP_FASTOPEN ideal-int
+pkg syscall (linux-s390x-cgo), const TCP_INFO = 11
+pkg syscall (linux-s390x-cgo), const TCP_INFO ideal-int
+pkg syscall (linux-s390x-cgo), const TCP_KEEPCNT = 6
@@ -4131,11 +3960,35 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x-cgo), const TCP_MD5SIG_MAXKEYLEN = 80
+pkg syscall (linux-s390x-cgo), const TCP_MD5SIG_MAXKEYLEN ideal-int
+pkg syscall (linux-s390x-cgo), const TCP_MSS = 512
++pkg syscall (linux-s390x-cgo), const TCP_MSS_DEFAULT = 536
++pkg syscall (linux-s390x-cgo), const TCP_MSS_DEFAULT ideal-int
++pkg syscall (linux-s390x-cgo), const TCP_MSS_DESIRED = 1220
++pkg syscall (linux-s390x-cgo), const TCP_MSS_DESIRED ideal-int
+pkg syscall (linux-s390x-cgo), const TCP_MSS ideal-int
++pkg syscall (linux-s390x-cgo), const TCP_QUEUE_SEQ = 21
++pkg syscall (linux-s390x-cgo), const TCP_QUEUE_SEQ ideal-int
+pkg syscall (linux-s390x-cgo), const TCP_QUICKACK = 12
+pkg syscall (linux-s390x-cgo), const TCP_QUICKACK ideal-int
++pkg syscall (linux-s390x-cgo), const TCP_REPAIR = 19
++pkg syscall (linux-s390x-cgo), const TCP_REPAIR ideal-int
++pkg syscall (linux-s390x-cgo), const TCP_REPAIR_OPTIONS = 22
++pkg syscall (linux-s390x-cgo), const TCP_REPAIR_OPTIONS ideal-int
++pkg syscall (linux-s390x-cgo), const TCP_REPAIR_QUEUE = 20
++pkg syscall (linux-s390x-cgo), const TCP_REPAIR_QUEUE ideal-int
++pkg syscall (linux-s390x-cgo), const TCP_S_DATA_IN = 4
++pkg syscall (linux-s390x-cgo), const TCP_S_DATA_IN ideal-int
++pkg syscall (linux-s390x-cgo), const TCP_S_DATA_OUT = 8
++pkg syscall (linux-s390x-cgo), const TCP_S_DATA_OUT ideal-int
+pkg syscall (linux-s390x-cgo), const TCP_SYNCNT = 7
+pkg syscall (linux-s390x-cgo), const TCP_SYNCNT ideal-int
++pkg syscall (linux-s390x-cgo), const TCP_THIN_DUPACK = 17
++pkg syscall (linux-s390x-cgo), const TCP_THIN_DUPACK ideal-int
++pkg syscall (linux-s390x-cgo), const TCP_THIN_LINEAR_TIMEOUTS = 16
++pkg syscall (linux-s390x-cgo), const TCP_THIN_LINEAR_TIMEOUTS ideal-int
++pkg syscall (linux-s390x-cgo), const TCP_TIMESTAMP = 24
++pkg syscall (linux-s390x-cgo), const TCP_TIMESTAMP ideal-int
++pkg syscall (linux-s390x-cgo), const TCP_USER_TIMEOUT = 18
++pkg syscall (linux-s390x-cgo), const TCP_USER_TIMEOUT ideal-int
+pkg syscall (linux-s390x-cgo), const TCP_WINDOW_CLAMP = 10
+pkg syscall (linux-s390x-cgo), const TCP_WINDOW_CLAMP ideal-int
+pkg syscall (linux-s390x-cgo), const TCSAFLUSH = 2
@@ -4286,6 +4139,8 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x-cgo), const TUNDETACHFILTER ideal-int
+pkg syscall (linux-s390x-cgo), const TUNGETFEATURES = 2147767503
+pkg syscall (linux-s390x-cgo), const TUNGETFEATURES ideal-int
++pkg syscall (linux-s390x-cgo), const TUNGETFILTER = 2148553947
++pkg syscall (linux-s390x-cgo), const TUNGETFILTER ideal-int
+pkg syscall (linux-s390x-cgo), const TUNGETIFF = 2147767506
+pkg syscall (linux-s390x-cgo), const TUNGETIFF ideal-int
+pkg syscall (linux-s390x-cgo), const TUNGETSNDBUF = 2147767507
@@ -4298,6 +4153,8 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x-cgo), const TUNSETGROUP ideal-int
+pkg syscall (linux-s390x-cgo), const TUNSETIFF = 1074025674
+pkg syscall (linux-s390x-cgo), const TUNSETIFF ideal-int
++pkg syscall (linux-s390x-cgo), const TUNSETIFINDEX = 1074025690
++pkg syscall (linux-s390x-cgo), const TUNSETIFINDEX ideal-int
+pkg syscall (linux-s390x-cgo), const TUNSETLINK = 1074025677
+pkg syscall (linux-s390x-cgo), const TUNSETLINK ideal-int
+pkg syscall (linux-s390x-cgo), const TUNSETNOCSUM = 1074025672
@@ -4574,7 +4431,6 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x-cgo), type Cmsghdr struct, Len uint64
+pkg syscall (linux-s390x-cgo), type Cmsghdr struct, Level int32
+pkg syscall (linux-s390x-cgo), type Cmsghdr struct, Type int32
-+pkg syscall (linux-s390x-cgo), type Cmsghdr struct, X__cmsg_data [0]uint8
+pkg syscall (linux-s390x-cgo), type Credential struct
+pkg syscall (linux-s390x-cgo), type Credential struct, Gid uint32
+pkg syscall (linux-s390x-cgo), type Credential struct, Groups []uint32
@@ -4628,7 +4484,6 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x-cgo), type InotifyEvent struct, Cookie uint32
+pkg syscall (linux-s390x-cgo), type InotifyEvent struct, Len uint32
+pkg syscall (linux-s390x-cgo), type InotifyEvent struct, Mask uint32
-+pkg syscall (linux-s390x-cgo), type InotifyEvent struct, Name [0]uint8
+pkg syscall (linux-s390x-cgo), type InotifyEvent struct, Wd int32
+pkg syscall (linux-s390x-cgo), type Iovec struct
+pkg syscall (linux-s390x-cgo), type Iovec struct, Base *uint8
@@ -4718,7 +4573,7 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x-cgo), type RawSockaddr struct, Family uint16
+pkg syscall (linux-s390x-cgo), type RawSockaddrUnix struct
+pkg syscall (linux-s390x-cgo), type RawSockaddrUnix struct, Family uint16
-+pkg syscall (linux-s390x-cgo), type RawSockaddrUnix struct, Path [108]int8
++pkg syscall (linux-s390x-cgo), type RawSockaddrUnix struct, Path [108]uint8
+pkg syscall (linux-s390x-cgo), type Rlimit struct
+pkg syscall (linux-s390x-cgo), type Rlimit struct, Cur uint64
+pkg syscall (linux-s390x-cgo), type Rlimit struct, Max uint64
@@ -4811,7 +4666,7 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x-cgo), type Stat_t struct, Rdev uint64
+pkg syscall (linux-s390x-cgo), type Stat_t struct, Size int64
+pkg syscall (linux-s390x-cgo), type Stat_t struct, Uid uint32
-+pkg syscall (linux-s390x-cgo), type Stat_t struct, X__unused [3]int64
++pkg syscall (linux-s390x-cgo), type Stat_t struct, X__glibc_reserved [3]int64
+pkg syscall (linux-s390x-cgo), type Sysinfo_t struct
+pkg syscall (linux-s390x-cgo), type Sysinfo_t struct, Bufferram uint64
+pkg syscall (linux-s390x-cgo), type Sysinfo_t struct, Freehigh uint64
@@ -4993,7 +4848,7 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x), const AF_LLC ideal-int
+pkg syscall (linux-s390x), const AF_LOCAL = 1
+pkg syscall (linux-s390x), const AF_LOCAL ideal-int
-+pkg syscall (linux-s390x), const AF_MAX = 40
++pkg syscall (linux-s390x), const AF_MAX = 41
+pkg syscall (linux-s390x), const AF_MAX ideal-int
+pkg syscall (linux-s390x), const AF_NETBEUI = 13
+pkg syscall (linux-s390x), const AF_NETBEUI ideal-int
@@ -5023,6 +4878,8 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x), const AF_SNA ideal-int
+pkg syscall (linux-s390x), const AF_TIPC = 30
+pkg syscall (linux-s390x), const AF_TIPC ideal-int
++pkg syscall (linux-s390x), const AF_VSOCK = 40
++pkg syscall (linux-s390x), const AF_VSOCK ideal-int
+pkg syscall (linux-s390x), const AF_WANPIPE = 25
+pkg syscall (linux-s390x), const AF_WANPIPE ideal-int
+pkg syscall (linux-s390x), const AF_X25 = 9
@@ -5587,8 +5444,6 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x), const EPOLLIN ideal-int
+pkg syscall (linux-s390x), const EPOLLMSG = 1024
+pkg syscall (linux-s390x), const EPOLLMSG ideal-int
-+pkg syscall (linux-s390x), const EPOLL_NONBLOCK = 2048
-+pkg syscall (linux-s390x), const EPOLL_NONBLOCK ideal-int
+pkg syscall (linux-s390x), const EPOLLONESHOT = 1073741824
+pkg syscall (linux-s390x), const EPOLLONESHOT ideal-int
+pkg syscall (linux-s390x), const EPOLLOUT = 4
@@ -5639,8 +5494,6 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x), const ETH_P_8021AH ideal-int
+pkg syscall (linux-s390x), const ETH_P_8021Q = 33024
+pkg syscall (linux-s390x), const ETH_P_8021Q ideal-int
-+pkg syscall (linux-s390x), const ETH_P_80221 = 35095
-+pkg syscall (linux-s390x), const ETH_P_80221 ideal-int
+pkg syscall (linux-s390x), const ETH_P_802_2 = 4
+pkg syscall (linux-s390x), const ETH_P_802_2 ideal-int
+pkg syscall (linux-s390x), const ETH_P_802_3 = 1
@@ -5901,12 +5754,8 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x), const IFA_F_DEPRECATED ideal-int
+pkg syscall (linux-s390x), const IFA_F_HOMEADDRESS = 16
+pkg syscall (linux-s390x), const IFA_F_HOMEADDRESS ideal-int
-+pkg syscall (linux-s390x), const IFA_F_MANAGETEMPADDR = 256
-+pkg syscall (linux-s390x), const IFA_F_MANAGETEMPADDR ideal-int
+pkg syscall (linux-s390x), const IFA_F_NODAD = 2
+pkg syscall (linux-s390x), const IFA_F_NODAD ideal-int
-+pkg syscall (linux-s390x), const IFA_F_NOPREFIXROUTE = 512
-+pkg syscall (linux-s390x), const IFA_F_NOPREFIXROUTE ideal-int
+pkg syscall (linux-s390x), const IFA_F_OPTIMISTIC = 4
+pkg syscall (linux-s390x), const IFA_F_OPTIMISTIC ideal-int
+pkg syscall (linux-s390x), const IFA_F_PERMANENT = 128
@@ -5921,7 +5770,7 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x), const IFA_LABEL ideal-int
+pkg syscall (linux-s390x), const IFA_LOCAL = 2
+pkg syscall (linux-s390x), const IFA_LOCAL ideal-int
-+pkg syscall (linux-s390x), const IFA_MAX = 8
++pkg syscall (linux-s390x), const IFA_MAX = 7
+pkg syscall (linux-s390x), const IFA_MAX ideal-int
+pkg syscall (linux-s390x), const IFA_MULTICAST = 7
+pkg syscall (linux-s390x), const IFA_MULTICAST ideal-int
@@ -5977,6 +5826,8 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x), const IFF_MULTI_QUEUE ideal-int
+pkg syscall (linux-s390x), const IFF_NOARP = 128
+pkg syscall (linux-s390x), const IFF_NOARP ideal-int
++pkg syscall (linux-s390x), const IFF_NOFILTER = 4096
++pkg syscall (linux-s390x), const IFF_NOFILTER ideal-int
+pkg syscall (linux-s390x), const IFF_NO_PI = 4096
+pkg syscall (linux-s390x), const IFF_NO_PI ideal-int
+pkg syscall (linux-s390x), const IFF_NOTRAILERS = 32
@@ -5985,6 +5836,8 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x), const IFF_ONE_QUEUE ideal-int
+pkg syscall (linux-s390x), const IFF_OVS_DATAPATH = 32768
+pkg syscall (linux-s390x), const IFF_OVS_DATAPATH ideal-int
++pkg syscall (linux-s390x), const IFF_PERSIST = 2048
++pkg syscall (linux-s390x), const IFF_PERSIST ideal-int
+pkg syscall (linux-s390x), const IFF_POINTOPOINT = 16
+pkg syscall (linux-s390x), const IFF_POINTOPOINT ideal-int
+pkg syscall (linux-s390x), const IFF_PORTSEL = 8192
@@ -6221,6 +6074,8 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x), const IP_PMTUDISC_WANT ideal-int
+pkg syscall (linux-s390x), const IPPROTO_AH = 51
+pkg syscall (linux-s390x), const IPPROTO_AH ideal-int
++pkg syscall (linux-s390x), const IPPROTO_BEETPH = 94
++pkg syscall (linux-s390x), const IPPROTO_BEETPH ideal-int
+pkg syscall (linux-s390x), const IPPROTO_COMP = 108
+pkg syscall (linux-s390x), const IPPROTO_COMP ideal-int
+pkg syscall (linux-s390x), const IPPROTO_DCCP = 33
@@ -6249,6 +6104,8 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x), const IPPROTO_IGMP ideal-int
+pkg syscall (linux-s390x), const IPPROTO_IPIP = 4
+pkg syscall (linux-s390x), const IPPROTO_IPIP ideal-int
++pkg syscall (linux-s390x), const IPPROTO_MH = 135
++pkg syscall (linux-s390x), const IPPROTO_MH ideal-int
+pkg syscall (linux-s390x), const IPPROTO_MTP = 92
+pkg syscall (linux-s390x), const IPPROTO_MTP ideal-int
+pkg syscall (linux-s390x), const IPPROTO_NONE = 59
@@ -6474,8 +6331,10 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x), const MAP_FIXED ideal-int
+pkg syscall (linux-s390x), const MAP_GROWSDOWN = 256
+pkg syscall (linux-s390x), const MAP_GROWSDOWN ideal-int
-+pkg syscall (linux-s390x), const MAP_GROWSUP = 512
-+pkg syscall (linux-s390x), const MAP_GROWSUP ideal-int
++pkg syscall (linux-s390x), const MAP_HUGE_MASK = 63
++pkg syscall (linux-s390x), const MAP_HUGE_MASK ideal-int
++pkg syscall (linux-s390x), const MAP_HUGE_SHIFT = 26
++pkg syscall (linux-s390x), const MAP_HUGE_SHIFT ideal-int
+pkg syscall (linux-s390x), const MAP_HUGETLB = 262144
+pkg syscall (linux-s390x), const MAP_HUGETLB ideal-int
+pkg syscall (linux-s390x), const MAP_LOCKED = 8192
@@ -6762,6 +6621,8 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x), const O_RSYNC = 1052672
+pkg syscall (linux-s390x), const O_RSYNC ideal-int
+pkg syscall (linux-s390x), const O_SYNC = 1052672
++pkg syscall (linux-s390x), const O_TMPFILE = 4259840
++pkg syscall (linux-s390x), const O_TMPFILE ideal-int
+pkg syscall (linux-s390x), const O_TRUNC = 512
+pkg syscall (linux-s390x), const PACKET_ADD_MEMBERSHIP = 1
+pkg syscall (linux-s390x), const PACKET_ADD_MEMBERSHIP ideal-int
@@ -6917,8 +6778,6 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x), const PR_GET_SECCOMP ideal-int
+pkg syscall (linux-s390x), const PR_GET_SECUREBITS = 27
+pkg syscall (linux-s390x), const PR_GET_SECUREBITS ideal-int
-+pkg syscall (linux-s390x), const PR_GET_THP_DISABLE = 42
-+pkg syscall (linux-s390x), const PR_GET_THP_DISABLE ideal-int
+pkg syscall (linux-s390x), const PR_GET_TID_ADDRESS = 40
+pkg syscall (linux-s390x), const PR_GET_TID_ADDRESS ideal-int
+pkg syscall (linux-s390x), const PR_GET_TIMERSLACK = 30
@@ -7015,8 +6874,6 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x), const PR_SET_SECCOMP ideal-int
+pkg syscall (linux-s390x), const PR_SET_SECUREBITS = 28
+pkg syscall (linux-s390x), const PR_SET_SECUREBITS ideal-int
-+pkg syscall (linux-s390x), const PR_SET_THP_DISABLE = 41
-+pkg syscall (linux-s390x), const PR_SET_THP_DISABLE ideal-int
+pkg syscall (linux-s390x), const PR_SET_TIMERSLACK = 29
+pkg syscall (linux-s390x), const PR_SET_TIMERSLACK ideal-int
+pkg syscall (linux-s390x), const PR_SET_TIMING = 14
@@ -7193,6 +7050,8 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x), const PTRACE_GETREGS ideal-int
+pkg syscall (linux-s390x), const PTRACE_GETSIGINFO = 16898
+pkg syscall (linux-s390x), const PTRACE_GETSIGINFO ideal-int
++pkg syscall (linux-s390x), const PTRACE_GETSIGMASK = 16906
++pkg syscall (linux-s390x), const PTRACE_GETSIGMASK ideal-int
+pkg syscall (linux-s390x), const PTRACE_INTERRUPT = 16903
+pkg syscall (linux-s390x), const PTRACE_INTERRUPT ideal-int
+pkg syscall (linux-s390x), const PTRACE_KILL = 8
@@ -7265,10 +7124,14 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x), const PTRACE_SETREGS ideal-int
+pkg syscall (linux-s390x), const PTRACE_SETSIGINFO = 16899
+pkg syscall (linux-s390x), const PTRACE_SETSIGINFO ideal-int
++pkg syscall (linux-s390x), const PTRACE_SETSIGMASK = 16907
++pkg syscall (linux-s390x), const PTRACE_SETSIGMASK ideal-int
+pkg syscall (linux-s390x), const PTRACE_SINGLESTEP = 9
+pkg syscall (linux-s390x), const PTRACE_SINGLESTEP ideal-int
+pkg syscall (linux-s390x), const PTRACE_SYSCALL = 24
+pkg syscall (linux-s390x), const PTRACE_SYSCALL ideal-int
++pkg syscall (linux-s390x), const PTRACE_TE_ABORT_RAND = 20497
++pkg syscall (linux-s390x), const PTRACE_TE_ABORT_RAND ideal-int
+pkg syscall (linux-s390x), const PTRACE_TRACEME = 0
+pkg syscall (linux-s390x), const PTRACE_TRACEME ideal-int
+pkg syscall (linux-s390x), const RLIM_INFINITY = -1
@@ -7339,7 +7202,7 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x), const RTAX_INITRWND ideal-int
+pkg syscall (linux-s390x), const RTAX_LOCK = 1
+pkg syscall (linux-s390x), const RTAX_LOCK ideal-int
-+pkg syscall (linux-s390x), const RTAX_MAX = 23
++pkg syscall (linux-s390x), const RTAX_MAX = 15
+pkg syscall (linux-s390x), const RTAX_MAX ideal-int
+pkg syscall (linux-s390x), const RTAX_MTU = 2
+pkg syscall (linux-s390x), const RTAX_MTU ideal-int
@@ -7937,8 +7800,6 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x), const SO_ATTACH_FILTER ideal-int
+pkg syscall (linux-s390x), const SO_BINDTODEVICE = 25
+pkg syscall (linux-s390x), const SO_BINDTODEVICE ideal-int
-+pkg syscall (linux-s390x), const SO_BPF_EXTENSIONS = 48
-+pkg syscall (linux-s390x), const SO_BPF_EXTENSIONS ideal-int
+pkg syscall (linux-s390x), const SO_BROADCAST = 6
+pkg syscall (linux-s390x), const SO_BSDCOMPAT = 14
+pkg syscall (linux-s390x), const SO_BSDCOMPAT ideal-int
@@ -8634,10 +8495,24 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x), const TCOFLUSH ideal-int
+pkg syscall (linux-s390x), const TCP_CONGESTION = 13
+pkg syscall (linux-s390x), const TCP_CONGESTION ideal-int
++pkg syscall (linux-s390x), const TCP_COOKIE_IN_ALWAYS = 1
++pkg syscall (linux-s390x), const TCP_COOKIE_IN_ALWAYS ideal-int
++pkg syscall (linux-s390x), const TCP_COOKIE_MAX = 16
++pkg syscall (linux-s390x), const TCP_COOKIE_MAX ideal-int
++pkg syscall (linux-s390x), const TCP_COOKIE_MIN = 8
++pkg syscall (linux-s390x), const TCP_COOKIE_MIN ideal-int
++pkg syscall (linux-s390x), const TCP_COOKIE_OUT_NEVER = 2
++pkg syscall (linux-s390x), const TCP_COOKIE_OUT_NEVER ideal-int
++pkg syscall (linux-s390x), const TCP_COOKIE_PAIR_SIZE = 32
++pkg syscall (linux-s390x), const TCP_COOKIE_PAIR_SIZE ideal-int
++pkg syscall (linux-s390x), const TCP_COOKIE_TRANSACTIONS = 15
++pkg syscall (linux-s390x), const TCP_COOKIE_TRANSACTIONS ideal-int
+pkg syscall (linux-s390x), const TCP_CORK = 3
+pkg syscall (linux-s390x), const TCP_CORK ideal-int
+pkg syscall (linux-s390x), const TCP_DEFER_ACCEPT = 9
+pkg syscall (linux-s390x), const TCP_DEFER_ACCEPT ideal-int
++pkg syscall (linux-s390x), const TCP_FASTOPEN = 23
++pkg syscall (linux-s390x), const TCP_FASTOPEN ideal-int
+pkg syscall (linux-s390x), const TCP_INFO = 11
+pkg syscall (linux-s390x), const TCP_INFO ideal-int
+pkg syscall (linux-s390x), const TCP_KEEPCNT = 6
@@ -8659,11 +8534,35 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x), const TCP_MD5SIG_MAXKEYLEN = 80
+pkg syscall (linux-s390x), const TCP_MD5SIG_MAXKEYLEN ideal-int
+pkg syscall (linux-s390x), const TCP_MSS = 512
++pkg syscall (linux-s390x), const TCP_MSS_DEFAULT = 536
++pkg syscall (linux-s390x), const TCP_MSS_DEFAULT ideal-int
++pkg syscall (linux-s390x), const TCP_MSS_DESIRED = 1220
++pkg syscall (linux-s390x), const TCP_MSS_DESIRED ideal-int
+pkg syscall (linux-s390x), const TCP_MSS ideal-int
++pkg syscall (linux-s390x), const TCP_QUEUE_SEQ = 21
++pkg syscall (linux-s390x), const TCP_QUEUE_SEQ ideal-int
+pkg syscall (linux-s390x), const TCP_QUICKACK = 12
+pkg syscall (linux-s390x), const TCP_QUICKACK ideal-int
++pkg syscall (linux-s390x), const TCP_REPAIR = 19
++pkg syscall (linux-s390x), const TCP_REPAIR ideal-int
++pkg syscall (linux-s390x), const TCP_REPAIR_OPTIONS = 22
++pkg syscall (linux-s390x), const TCP_REPAIR_OPTIONS ideal-int
++pkg syscall (linux-s390x), const TCP_REPAIR_QUEUE = 20
++pkg syscall (linux-s390x), const TCP_REPAIR_QUEUE ideal-int
++pkg syscall (linux-s390x), const TCP_S_DATA_IN = 4
++pkg syscall (linux-s390x), const TCP_S_DATA_IN ideal-int
++pkg syscall (linux-s390x), const TCP_S_DATA_OUT = 8
++pkg syscall (linux-s390x), const TCP_S_DATA_OUT ideal-int
+pkg syscall (linux-s390x), const TCP_SYNCNT = 7
+pkg syscall (linux-s390x), const TCP_SYNCNT ideal-int
++pkg syscall (linux-s390x), const TCP_THIN_DUPACK = 17
++pkg syscall (linux-s390x), const TCP_THIN_DUPACK ideal-int
++pkg syscall (linux-s390x), const TCP_THIN_LINEAR_TIMEOUTS = 16
++pkg syscall (linux-s390x), const TCP_THIN_LINEAR_TIMEOUTS ideal-int
++pkg syscall (linux-s390x), const TCP_TIMESTAMP = 24
++pkg syscall (linux-s390x), const TCP_TIMESTAMP ideal-int
++pkg syscall (linux-s390x), const TCP_USER_TIMEOUT = 18
++pkg syscall (linux-s390x), const TCP_USER_TIMEOUT ideal-int
+pkg syscall (linux-s390x), const TCP_WINDOW_CLAMP = 10
+pkg syscall (linux-s390x), const TCP_WINDOW_CLAMP ideal-int
+pkg syscall (linux-s390x), const TCSAFLUSH = 2
@@ -8814,6 +8713,8 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x), const TUNDETACHFILTER ideal-int
+pkg syscall (linux-s390x), const TUNGETFEATURES = 2147767503
+pkg syscall (linux-s390x), const TUNGETFEATURES ideal-int
++pkg syscall (linux-s390x), const TUNGETFILTER = 2148553947
++pkg syscall (linux-s390x), const TUNGETFILTER ideal-int
+pkg syscall (linux-s390x), const TUNGETIFF = 2147767506
+pkg syscall (linux-s390x), const TUNGETIFF ideal-int
+pkg syscall (linux-s390x), const TUNGETSNDBUF = 2147767507
@@ -8826,6 +8727,8 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x), const TUNSETGROUP ideal-int
+pkg syscall (linux-s390x), const TUNSETIFF = 1074025674
+pkg syscall (linux-s390x), const TUNSETIFF ideal-int
++pkg syscall (linux-s390x), const TUNSETIFINDEX = 1074025690
++pkg syscall (linux-s390x), const TUNSETIFINDEX ideal-int
+pkg syscall (linux-s390x), const TUNSETLINK = 1074025677
+pkg syscall (linux-s390x), const TUNSETLINK ideal-int
+pkg syscall (linux-s390x), const TUNSETNOCSUM = 1074025672
@@ -9102,7 +9005,6 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x), type Cmsghdr struct, Len uint64
+pkg syscall (linux-s390x), type Cmsghdr struct, Level int32
+pkg syscall (linux-s390x), type Cmsghdr struct, Type int32
-+pkg syscall (linux-s390x), type Cmsghdr struct, X__cmsg_data [0]uint8
+pkg syscall (linux-s390x), type Credential struct
+pkg syscall (linux-s390x), type Credential struct, Gid uint32
+pkg syscall (linux-s390x), type Credential struct, Groups []uint32
@@ -9156,7 +9058,6 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x), type InotifyEvent struct, Cookie uint32
+pkg syscall (linux-s390x), type InotifyEvent struct, Len uint32
+pkg syscall (linux-s390x), type InotifyEvent struct, Mask uint32
-+pkg syscall (linux-s390x), type InotifyEvent struct, Name [0]uint8
+pkg syscall (linux-s390x), type InotifyEvent struct, Wd int32
+pkg syscall (linux-s390x), type Iovec struct
+pkg syscall (linux-s390x), type Iovec struct, Base *uint8
@@ -9246,7 +9147,7 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x), type RawSockaddr struct, Family uint16
+pkg syscall (linux-s390x), type RawSockaddrUnix struct
+pkg syscall (linux-s390x), type RawSockaddrUnix struct, Family uint16
-+pkg syscall (linux-s390x), type RawSockaddrUnix struct, Path [108]int8
++pkg syscall (linux-s390x), type RawSockaddrUnix struct, Path [108]uint8
+pkg syscall (linux-s390x), type Rlimit struct
+pkg syscall (linux-s390x), type Rlimit struct, Cur uint64
+pkg syscall (linux-s390x), type Rlimit struct, Max uint64
@@ -9339,7 +9240,7 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x), type Stat_t struct, Rdev uint64
+pkg syscall (linux-s390x), type Stat_t struct, Size int64
+pkg syscall (linux-s390x), type Stat_t struct, Uid uint32
-+pkg syscall (linux-s390x), type Stat_t struct, X__unused [3]int64
++pkg syscall (linux-s390x), type Stat_t struct, X__glibc_reserved [3]int64
+pkg syscall (linux-s390x), type Sysinfo_t struct
+pkg syscall (linux-s390x), type Sysinfo_t struct, Bufferram uint64
+pkg syscall (linux-s390x), type Sysinfo_t struct, Freehigh uint64
@@ -9478,12 +9379,31 @@ index d63efd0..6261e9c 100644
+pkg syscall (linux-s390x), var Stderr int
+pkg syscall (linux-s390x), var Stdin int
+pkg syscall (linux-s390x), var Stdout int
+diff --git a/misc/cgo/test/issue13930.go b/misc/cgo/test/issue13930.go
+new file mode 100644
+index 0000000..3a22459
+--- /dev/null
++++ b/misc/cgo/test/issue13930.go
+@@ -0,0 +1,13 @@
++// Copyright 2016 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++// Issue 13930. Test that cgo's multiple-value special form for
++// C function calls works in variable declaration statements.
++
++package cgotest
++
++// #include <stdlib.h>
++import "C"
++
++var _, _ = C.abs(0)
diff --git a/misc/cgo/test/issue9400/asm_s390x.s b/misc/cgo/test/issue9400/asm_s390x.s
new file mode 100644
-index 0000000..ffe260a
+index 0000000..6330cdf
--- /dev/null
+++ b/misc/cgo/test/issue9400/asm_s390x.s
-@@ -0,0 +1,31 @@
+@@ -0,0 +1,26 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
@@ -9495,26 +9415,35 @@ index 0000000..ffe260a
+TEXT ·RewindAndSetgid(SB),NOSPLIT,$0-0
+ // Rewind stack pointer so anything that happens on the stack
+ // will clobber the test pattern created by the caller
-+ // TODO(mundaym): Code generator should support ADD $(1024 * 8), R15
-+ MOVD $(1024 * 8), R4
-+ ADD R4, R15
++ ADD $(1024 * 8), R15
+
+ // Ask signaller to setgid
-+ // TODO(mundaym): Code generator should support MOVW $1, ·Baton(SB)
+ MOVD $·Baton(SB), R5
-+ MOVW $1, R6
-+ MOVW R6, 0(R5)
++ MOVW $1, 0(R5)
+
+ // Wait for setgid completion
+loop:
+ SYNC
+ MOVW ·Baton(SB), R3
-+ CMP R3, $0
-+ BNE loop
++ CMPBNE R3, $0, loop
+
+ // Restore stack
-+ SUB R4, R15
++ SUB $(1024 * 8), R15
+ RET
+diff --git a/misc/nacl/testzip.proto b/misc/nacl/testzip.proto
+index 4e82ac9..dcb1563 100644
+--- a/misc/nacl/testzip.proto
++++ b/misc/nacl/testzip.proto
+@@ -44,6 +44,9 @@ go src=..
+ gofmt_test.go
+ testdata
+ +
++ newlink
++ testdata
++ +
+ archive
+ tar
+ testdata
diff --git a/src/cmd/api/goapi.go b/src/cmd/api/goapi.go
index 8b20d12..373e71e 100644
--- a/src/cmd/api/goapi.go
@@ -9529,7 +9458,7 @@ index 8b20d12..373e71e 100644
{GOOS: "darwin", GOARCH: "386"},
{GOOS: "darwin", GOARCH: "amd64", CgoEnabled: true},
diff --git a/src/cmd/asm/internal/arch/arch.go b/src/cmd/asm/internal/arch/arch.go
-index c14a13c..4cf5fb7 100644
+index c14a13c..51982a2 100644
--- a/src/cmd/asm/internal/arch/arch.go
+++ b/src/cmd/asm/internal/arch/arch.go
@@ -10,6 +10,7 @@ import (
@@ -9551,7 +9480,16 @@ index c14a13c..4cf5fb7 100644
}
return nil
}
-@@ -426,3 +431,53 @@ func archMips64() *Arch {
+@@ -162,8 +167,6 @@ func archX86(linkArch *obj.LinkArch) *Arch {
+ instructions["MOVDQ2Q"] = x86.AMOVQ
+ instructions["MOVNTDQ"] = x86.AMOVNTO
+ instructions["MOVOA"] = x86.AMOVO
+- instructions["PF2ID"] = x86.APF2IL
+- instructions["PI2FD"] = x86.API2FL
+ instructions["PSLLDQ"] = x86.APSLLO
+ instructions["PSRLDQ"] = x86.APSRLO
+ instructions["PADDD"] = x86.APADDL
+@@ -426,3 +429,56 @@ func archMips64() *Arch {
IsJump: jumpMIPS64,
}
}
@@ -9566,6 +9504,9 @@ index c14a13c..4cf5fb7 100644
+ for i := s390x.REG_F0; i <= s390x.REG_F15; i++ {
+ register[obj.Rconv(i)] = int16(i)
+ }
++ for i := s390x.REG_V0; i <= s390x.REG_V31; i++ {
++ register[obj.Rconv(i)] = int16(i)
++ }
+ for i := s390x.REG_AR0; i <= s390x.REG_AR15; i++ {
+ register[obj.Rconv(i)] = int16(i)
+ }
@@ -9607,10 +9548,10 @@ index c14a13c..4cf5fb7 100644
+}
diff --git a/src/cmd/asm/internal/arch/s390x.go b/src/cmd/asm/internal/arch/s390x.go
new file mode 100644
-index 0000000..62a8101
+index 0000000..2b32492
--- /dev/null
+++ b/src/cmd/asm/internal/arch/s390x.go
-@@ -0,0 +1,116 @@
+@@ -0,0 +1,136 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
@@ -9700,12 +9641,28 @@ index 0000000..62a8101
+ return false
+}
+
-+// IsS390xStorageAndStorage reports whether the op (as defined by an s390x.A* constant) refers
-+// to an storage-and-storage format instruction such as mvc, clc, xc, oc or nc.
-+func IsS390xStorageAndStorage(op int) bool {
++// IsS390xWithLength reports whether the op (as defined by an s390x.A* constant)
++// refers to an instruction which takes a length as its first argument.
++func IsS390xWithLength(op int) bool {
+ switch op {
+ case s390x.AMVC, s390x.ACLC, s390x.AXC, s390x.AOC, s390x.ANC:
+ return true
++ case s390x.AVLL, s390x.AVSTL:
++ return true
++ }
++ return false
++}
++
++// IsS390xWithIndex reports whether the op (as defined by an s390x.A* constant)
++// refers to an instruction which takes an index as its first argument.
++func IsS390xWithIndex(op int) bool {
++ switch op {
++ case s390x.AVSCEG, s390x.AVSCEF, s390x.AVGEG, s390x.AVGEF:
++ return true
++ case s390x.AVGMG, s390x.AVGMF, s390x.AVGMH, s390x.AVGMB:
++ return true
++ case s390x.AVLEIG, s390x.AVLEIF, s390x.AVLEIH, s390x.AVLEIB:
++ return true
+ }
+ return false
+}
@@ -9724,11 +9681,15 @@ index 0000000..62a8101
+ if 0 <= n && n <= 15 {
+ return s390x.REG_R0 + n, true
+ }
++ case "V":
++ if 0 <= n && n <= 31 {
++ return s390x.REG_V0 + n, true
++ }
+ }
+ return 0, false
+}
diff --git a/src/cmd/asm/internal/asm/asm.go b/src/cmd/asm/internal/asm/asm.go
-index 9827d70..f67e8ee 100644
+index 9827d70..bb0b3aa 100644
--- a/src/cmd/asm/internal/asm/asm.go
+++ b/src/cmd/asm/internal/asm/asm.go
@@ -381,6 +381,20 @@ func (p *Parser) asmJump(op int, cond string, a []obj.Addr) {
@@ -9757,7 +9718,7 @@ index 9827d70..f67e8ee 100644
return
}
+ case 'z':
-+ if arch.IsS390xStorageAndStorage(op) {
++ if arch.IsS390xWithLength(op) || arch.IsS390xWithIndex(op) {
+ prog.From = a[1]
+ prog.From3 = newAddr(a[0])
+ } else {
@@ -9768,6 +9729,52 @@ index 9827d70..f67e8ee 100644
default:
p.errorf("TODO: implement three-operand instructions for this architecture")
return
+@@ -628,6 +651,13 @@ func (p *Parser) asmInstruction(op int, cond string, a []obj.Addr) {
+ prog.To = a[3]
+ break
+ }
++ if p.arch.Thechar == 'z' {
++ prog.From = a[1]
++ prog.Reg = p.getRegister(prog, op, &a[2])
++ prog.From3 = newAddr(a[0])
++ prog.To = a[3]
++ break
++ }
+ p.errorf("can't handle %s instruction with 4 operands", obj.Aconv(op))
+ return
+ case 5:
+diff --git a/src/cmd/cgo/ast.go b/src/cmd/cgo/ast.go
+index c3a24c2..4c5dc9a 100644
+--- a/src/cmd/cgo/ast.go
++++ b/src/cmd/cgo/ast.go
+@@ -447,7 +447,11 @@ func (f *File) walk(x interface{}, context string, visit func(*File, interface{}
+ case *ast.ImportSpec:
+ case *ast.ValueSpec:
+ f.walk(&n.Type, "type", visit)
+- f.walk(n.Values, "expr", visit)
++ if len(n.Names) == 2 && len(n.Values) == 1 {
++ f.walk(&n.Values[0], "as2", visit)
++ } else {
++ f.walk(n.Values, "expr", visit)
++ }
+ case *ast.TypeSpec:
+ f.walk(&n.Type, "type", visit)
+
+diff --git a/src/cmd/cgo/doc.go b/src/cmd/cgo/doc.go
+index bd38a5c..8b4e2bf 100644
+--- a/src/cmd/cgo/doc.go
++++ b/src/cmd/cgo/doc.go
+@@ -148,8 +148,9 @@ assignment context to retrieve both the return value (if any) and the
+ C errno variable as an error (use _ to skip the result value if the
+ function returns void). For example:
+
+- n, err := C.sqrt(-1)
++ n, err = C.sqrt(-1)
+ _, err := C.voidFunc()
++ var n, err = C.sqrt(1)
+
+ Calling C function pointers is currently not supported, however you can
+ declare Go variables which hold C function pointers and pass them
diff --git a/src/cmd/cgo/main.go b/src/cmd/cgo/main.go
index 0906ceb..ff82e16 100644
--- a/src/cmd/cgo/main.go
@@ -9793,36 +9800,303 @@ index ca0ec0a..912c6c6 100644
// Write second Go output: definitions of _C_xxx.
// In a separate file so that the import of "unsafe" does not
+diff --git a/src/cmd/cgo/util.go b/src/cmd/cgo/util.go
+index 3adb8e8..52ca160 100644
+--- a/src/cmd/cgo/util.go
++++ b/src/cmd/cgo/util.go
+@@ -8,6 +8,7 @@ import (
+ "bytes"
+ "fmt"
+ "go/token"
++ "io/ioutil"
+ "os"
+ "os/exec"
+ )
+@@ -16,6 +17,43 @@ import (
+ // It returns the output to standard output and standard error.
+ // ok indicates whether the command exited successfully.
+ func run(stdin []byte, argv []string) (stdout, stderr []byte, ok bool) {
++ if i := find(argv, "-xc"); i >= 0 && argv[len(argv)-1] == "-" {
++ // Some compilers have trouble with standard input.
++ // Others have trouble with -xc.
++ // Avoid both problems by writing a file with a .c extension.
++ f, err := ioutil.TempFile("", "cgo-gcc-input-")
++ if err != nil {
++ fatalf("%s", err)
++ }
++ name := f.Name()
++ f.Close()
++ if err := ioutil.WriteFile(name+".c", stdin, 0666); err != nil {
++ os.Remove(name)
++ fatalf("%s", err)
++ }
++ defer os.Remove(name)
++ defer os.Remove(name + ".c")
++
++ // Build new argument list without -xc and trailing -.
++ new := append(argv[:i:i], argv[i+1:len(argv)-1]...)
++
++ // Since we are going to write the file to a temporary directory,
++ // we will need to add -I . explicitly to the command line:
++ // any #include "foo" before would have looked in the current
++ // directory as the directory "holding" standard input, but now
++ // the temporary directory holds the input.
++ // We've also run into compilers that reject "-I." but allow "-I", ".",
++ // so be sure to use two arguments.
++ // This matters mainly for people invoking cgo -godefs by hand.
++ new = append(new, "-I", ".")
++
++ // Finish argument list with path to C file.
++ new = append(new, name+".c")
++
++ argv = new
++ stdin = nil
++ }
++
+ p := exec.Command(argv[0], argv[1:]...)
+ p.Stdin = bytes.NewReader(stdin)
+ var bout, berr bytes.Buffer
+@@ -30,6 +68,15 @@ func run(stdin []byte, argv []string) (stdout, stderr []byte, ok bool) {
+ return
+ }
+
++func find(argv []string, target string) int {
++ for i, arg := range argv {
++ if arg == target {
++ return i
++ }
++ }
++ return -1
++}
++
+ func lineno(pos token.Pos) string {
+ return fset.Position(pos).String()
+ }
+diff --git a/src/cmd/compile/internal/big/ratconv.go b/src/cmd/compile/internal/big/ratconv.go
+index 4566ff4..57df124 100644
+--- a/src/cmd/compile/internal/big/ratconv.go
++++ b/src/cmd/compile/internal/big/ratconv.go
+@@ -15,7 +15,7 @@ import (
+ )
+
+ func ratTok(ch rune) bool {
+- return strings.IndexRune("+-/0123456789.eE", ch) >= 0
++ return strings.ContainsRune("+-/0123456789.eE", ch)
+ }
+
+ // Scan is a support routine for fmt.Scanner. It accepts the formats
+@@ -25,7 +25,7 @@ func (z *Rat) Scan(s fmt.ScanState, ch rune) error {
+ if err != nil {
+ return err
+ }
+- if strings.IndexRune("efgEFGv", ch) < 0 {
++ if !strings.ContainsRune("efgEFGv", ch) {
+ return errors.New("Rat.Scan: invalid verb")
+ }
+ if _, ok := z.SetString(string(tok)); !ok {
+diff --git a/src/cmd/compile/internal/gc/bexport.go b/src/cmd/compile/internal/gc/bexport.go
+index b49f0fb..3edd048 100644
+--- a/src/cmd/compile/internal/gc/bexport.go
++++ b/src/cmd/compile/internal/gc/bexport.go
+@@ -877,7 +877,7 @@ func (p *exporter) byte(b byte) {
+ // tracef is like fmt.Printf but it rewrites the format string
+ // to take care of indentation.
+ func (p *exporter) tracef(format string, args ...interface{}) {
+- if strings.IndexAny(format, "<>\n") >= 0 {
++ if strings.ContainsAny(format, "<>\n") {
+ var buf bytes.Buffer
+ for i := 0; i < len(format); i++ {
+ // no need to deal with runes
+diff --git a/src/cmd/compile/internal/gc/builtin.go b/src/cmd/compile/internal/gc/builtin.go
+index 4199fb3..7583e8f 100644
+--- a/src/cmd/compile/internal/gc/builtin.go
++++ b/src/cmd/compile/internal/gc/builtin.go
+@@ -3,7 +3,7 @@
+ package gc
+
+ const runtimeimport = "" +
+- "package runtime\n" +
++ "package runtime safe\n" +
+ "func @\"\".newobject (@\"\".typ·2 *byte) (? *any)\n" +
+ "func @\"\".panicindex ()\n" +
+ "func @\"\".panicslice ()\n" +
+@@ -44,7 +44,7 @@ const runtimeimport = "" +
+ "func @\"\".stringtoslicerune (? *[32]rune, ? string) (? []rune)\n" +
+ "func @\"\".stringiter (? string, ? int) (? int)\n" +
+ "func @\"\".stringiter2 (? string, ? int) (@\"\".retk·1 int, @\"\".retv·2 rune)\n" +
+- "func @\"\".slicecopy (@\"\".to·2 any, @\"\".fr·3 any, @\"\".wid·4 uintptr) (? int)\n" +
++ "func @\"\".slicecopy (@\"\".to·2 any, @\"\".fr·3 any, @\"\".wid·4 uintptr \"unsafe-uintptr\") (? int)\n" +
+ "func @\"\".slicestringcopy (@\"\".to·2 any, @\"\".fr·3 any) (? int)\n" +
+ "func @\"\".typ2Itab (@\"\".typ·2 *byte, @\"\".typ2·3 *byte, @\"\".cache·4 **byte) (@\"\".ret·1 *byte)\n" +
+ "func @\"\".convI2E (@\"\".elem·2 any) (@\"\".ret·1 any)\n" +
+@@ -91,31 +91,31 @@ const runtimeimport = "" +
+ "func @\"\".writebarrierstring (@\"\".dst·1 *any, @\"\".src·2 any)\n" +
+ "func @\"\".writebarrierslice (@\"\".dst·1 *any, @\"\".src·2 any)\n" +
+ "func @\"\".writebarrieriface (@\"\".dst·1 *any, @\"\".src·2 any)\n" +
+- "func @\"\".writebarrierfat01 (@\"\".dst·1 *any, _ uintptr, @\"\".src·3 any)\n" +
+- "func @\"\".writebarrierfat10 (@\"\".dst·1 *any, _ uintptr, @\"\".src·3 any)\n" +
+- "func @\"\".writebarrierfat11 (@\"\".dst·1 *any, _ uintptr, @\"\".src·3 any)\n" +
+- "func @\"\".writebarrierfat001 (@\"\".dst·1 *any, _ uintptr, @\"\".src·3 any)\n" +
+- "func @\"\".writebarrierfat010 (@\"\".dst·1 *any, _ uintptr, @\"\".src·3 any)\n" +
+- "func @\"\".writebarrierfat011 (@\"\".dst·1 *any, _ uintptr, @\"\".src·3 any)\n" +
+- "func @\"\".writebarrierfat100 (@\"\".dst·1 *any, _ uintptr, @\"\".src·3 any)\n" +
+- "func @\"\".writebarrierfat101 (@\"\".dst·1 *any, _ uintptr, @\"\".src·3 any)\n" +
+- "func @\"\".writebarrierfat110 (@\"\".dst·1 *any, _ uintptr, @\"\".src·3 any)\n" +
+- "func @\"\".writebarrierfat111 (@\"\".dst·1 *any, _ uintptr, @\"\".src·3 any)\n" +
+- "func @\"\".writebarrierfat0001 (@\"\".dst·1 *any, _ uintptr, @\"\".src·3 any)\n" +
+- "func @\"\".writebarrierfat0010 (@\"\".dst·1 *any, _ uintptr, @\"\".src·3 any)\n" +
+- "func @\"\".writebarrierfat0011 (@\"\".dst·1 *any, _ uintptr, @\"\".src·3 any)\n" +
+- "func @\"\".writebarrierfat0100 (@\"\".dst·1 *any, _ uintptr, @\"\".src·3 any)\n" +
+- "func @\"\".writebarrierfat0101 (@\"\".dst·1 *any, _ uintptr, @\"\".src·3 any)\n" +
+- "func @\"\".writebarrierfat0110 (@\"\".dst·1 *any, _ uintptr, @\"\".src·3 any)\n" +
+- "func @\"\".writebarrierfat0111 (@\"\".dst·1 *any, _ uintptr, @\"\".src·3 any)\n" +
+- "func @\"\".writebarrierfat1000 (@\"\".dst·1 *any, _ uintptr, @\"\".src·3 any)\n" +
+- "func @\"\".writebarrierfat1001 (@\"\".dst·1 *any, _ uintptr, @\"\".src·3 any)\n" +
+- "func @\"\".writebarrierfat1010 (@\"\".dst·1 *any, _ uintptr, @\"\".src·3 any)\n" +
+- "func @\"\".writebarrierfat1011 (@\"\".dst·1 *any, _ uintptr, @\"\".src·3 any)\n" +
+- "func @\"\".writebarrierfat1100 (@\"\".dst·1 *any, _ uintptr, @\"\".src·3 any)\n" +
+- "func @\"\".writebarrierfat1101 (@\"\".dst·1 *any, _ uintptr, @\"\".src·3 any)\n" +
+- "func @\"\".writebarrierfat1110 (@\"\".dst·1 *any, _ uintptr, @\"\".src·3 any)\n" +
+- "func @\"\".writebarrierfat1111 (@\"\".dst·1 *any, _ uintptr, @\"\".src·3 any)\n" +
++ "func @\"\".writebarrierfat01 (@\"\".dst·1 *any, _ uintptr \"unsafe-uintptr\", @\"\".src·3 any)\n" +
++ "func @\"\".writebarrierfat10 (@\"\".dst·1 *any, _ uintptr \"unsafe-uintptr\", @\"\".src·3 any)\n" +
++ "func @\"\".writebarrierfat11 (@\"\".dst·1 *any, _ uintptr \"unsafe-uintptr\", @\"\".src·3 any)\n" +
++ "func @\"\".writebarrierfat001 (@\"\".dst·1 *any, _ uintptr \"unsafe-uintptr\", @\"\".src·3 any)\n" +
++ "func @\"\".writebarrierfat010 (@\"\".dst·1 *any, _ uintptr \"unsafe-uintptr\", @\"\".src·3 any)\n" +
++ "func @\"\".writebarrierfat011 (@\"\".dst·1 *any, _ uintptr \"unsafe-uintptr\", @\"\".src·3 any)\n" +
++ "func @\"\".writebarrierfat100 (@\"\".dst·1 *any, _ uintptr \"unsafe-uintptr\", @\"\".src·3 any)\n" +
++ "func @\"\".writebarrierfat101 (@\"\".dst·1 *any, _ uintptr \"unsafe-uintptr\", @\"\".src·3 any)\n" +
++ "func @\"\".writebarrierfat110 (@\"\".dst·1 *any, _ uintptr \"unsafe-uintptr\", @\"\".src·3 any)\n" +
++ "func @\"\".writebarrierfat111 (@\"\".dst·1 *any, _ uintptr \"unsafe-uintptr\", @\"\".src·3 any)\n" +
++ "func @\"\".writebarrierfat0001 (@\"\".dst·1 *any, _ uintptr \"unsafe-uintptr\", @\"\".src·3 any)\n" +
++ "func @\"\".writebarrierfat0010 (@\"\".dst·1 *any, _ uintptr \"unsafe-uintptr\", @\"\".src·3 any)\n" +
++ "func @\"\".writebarrierfat0011 (@\"\".dst·1 *any, _ uintptr \"unsafe-uintptr\", @\"\".src·3 any)\n" +
++ "func @\"\".writebarrierfat0100 (@\"\".dst·1 *any, _ uintptr \"unsafe-uintptr\", @\"\".src·3 any)\n" +
++ "func @\"\".writebarrierfat0101 (@\"\".dst·1 *any, _ uintptr \"unsafe-uintptr\", @\"\".src·3 any)\n" +
++ "func @\"\".writebarrierfat0110 (@\"\".dst·1 *any, _ uintptr \"unsafe-uintptr\", @\"\".src·3 any)\n" +
++ "func @\"\".writebarrierfat0111 (@\"\".dst·1 *any, _ uintptr \"unsafe-uintptr\", @\"\".src·3 any)\n" +
++ "func @\"\".writebarrierfat1000 (@\"\".dst·1 *any, _ uintptr \"unsafe-uintptr\", @\"\".src·3 any)\n" +
++ "func @\"\".writebarrierfat1001 (@\"\".dst·1 *any, _ uintptr \"unsafe-uintptr\", @\"\".src·3 any)\n" +
++ "func @\"\".writebarrierfat1010 (@\"\".dst·1 *any, _ uintptr \"unsafe-uintptr\", @\"\".src·3 any)\n" +
++ "func @\"\".writebarrierfat1011 (@\"\".dst·1 *any, _ uintptr \"unsafe-uintptr\", @\"\".src·3 any)\n" +
++ "func @\"\".writebarrierfat1100 (@\"\".dst·1 *any, _ uintptr \"unsafe-uintptr\", @\"\".src·3 any)\n" +
++ "func @\"\".writebarrierfat1101 (@\"\".dst·1 *any, _ uintptr \"unsafe-uintptr\", @\"\".src·3 any)\n" +
++ "func @\"\".writebarrierfat1110 (@\"\".dst·1 *any, _ uintptr \"unsafe-uintptr\", @\"\".src·3 any)\n" +
++ "func @\"\".writebarrierfat1111 (@\"\".dst·1 *any, _ uintptr \"unsafe-uintptr\", @\"\".src·3 any)\n" +
+ "func @\"\".typedmemmove (@\"\".typ·1 *byte, @\"\".dst·2 *any, @\"\".src·3 *any)\n" +
+ "func @\"\".typedslicecopy (@\"\".typ·2 *byte, @\"\".dst·3 any, @\"\".src·4 any) (? int)\n" +
+ "func @\"\".selectnbsend (@\"\".chanType·2 *byte, @\"\".hchan·3 chan<- any, @\"\".elem·4 *any) (? bool)\n" +
+@@ -131,9 +131,9 @@ const runtimeimport = "" +
+ "func @\"\".makeslice (@\"\".typ·2 *byte, @\"\".nel·3 int64, @\"\".cap·4 int64) (@\"\".ary·1 []any)\n" +
+ "func @\"\".growslice (@\"\".typ·2 *byte, @\"\".old·3 []any, @\"\".cap·4 int) (@\"\".ary·1 []any)\n" +
+ "func @\"\".growslice_n (@\"\".typ·2 *byte, @\"\".old·3 []any, @\"\".n·4 int) (@\"\".ary·1 []any)\n" +
+- "func @\"\".memmove (@\"\".to·1 *any, @\"\".frm·2 *any, @\"\".length·3 uintptr)\n" +
+- "func @\"\".memclr (@\"\".ptr·1 *byte, @\"\".length·2 uintptr)\n" +
+- "func @\"\".memequal (@\"\".x·2 *any, @\"\".y·3 *any, @\"\".size·4 uintptr) (? bool)\n" +
++ "func @\"\".memmove (@\"\".to·1 *any, @\"\".frm·2 *any, @\"\".length·3 uintptr \"unsafe-uintptr\")\n" +
++ "func @\"\".memclr (@\"\".ptr·1 *byte, @\"\".length·2 uintptr \"unsafe-uintptr\")\n" +
++ "func @\"\".memequal (@\"\".x·2 *any, @\"\".y·3 *any, @\"\".size·4 uintptr \"unsafe-uintptr\") (? bool)\n" +
+ "func @\"\".memequal8 (@\"\".x·2 *any, @\"\".y·3 *any) (? bool)\n" +
+ "func @\"\".memequal16 (@\"\".x·2 *any, @\"\".y·3 *any) (? bool)\n" +
+ "func @\"\".memequal32 (@\"\".x·2 *any, @\"\".y·3 *any) (? bool)\n" +
+@@ -148,14 +148,14 @@ const runtimeimport = "" +
+ "func @\"\".int64tofloat64 (? int64) (? float64)\n" +
+ "func @\"\".uint64tofloat64 (? uint64) (? float64)\n" +
+ "func @\"\".complex128div (@\"\".num·2 complex128, @\"\".den·3 complex128) (@\"\".quo·1 complex128)\n" +
+- "func @\"\".racefuncenter (? uintptr)\n" +
++ "func @\"\".racefuncenter (? uintptr \"unsafe-uintptr\")\n" +
+ "func @\"\".racefuncexit ()\n" +
+- "func @\"\".raceread (? uintptr)\n" +
+- "func @\"\".racewrite (? uintptr)\n" +
+- "func @\"\".racereadrange (@\"\".addr·1 uintptr, @\"\".size·2 uintptr)\n" +
+- "func @\"\".racewriterange (@\"\".addr·1 uintptr, @\"\".size·2 uintptr)\n" +
+- "func @\"\".msanread (@\"\".addr·1 uintptr, @\"\".size·2 uintptr)\n" +
+- "func @\"\".msanwrite (@\"\".addr·1 uintptr, @\"\".size·2 uintptr)\n" +
++ "func @\"\".raceread (? uintptr \"unsafe-uintptr\")\n" +
++ "func @\"\".racewrite (? uintptr \"unsafe-uintptr\")\n" +
++ "func @\"\".racereadrange (@\"\".addr·1 uintptr \"unsafe-uintptr\", @\"\".size·2 uintptr \"unsafe-uintptr\")\n" +
++ "func @\"\".racewriterange (@\"\".addr·1 uintptr \"unsafe-uintptr\", @\"\".size·2 uintptr \"unsafe-uintptr\")\n" +
++ "func @\"\".msanread (@\"\".addr·1 uintptr \"unsafe-uintptr\", @\"\".size·2 uintptr \"unsafe-uintptr\")\n" +
++ "func @\"\".msanwrite (@\"\".addr·1 uintptr \"unsafe-uintptr\", @\"\".size·2 uintptr \"unsafe-uintptr\")\n" +
+ "\n" +
+ "$$\n"
+
+diff --git a/src/cmd/compile/internal/gc/builtin/runtime.go b/src/cmd/compile/internal/gc/builtin/runtime.go
+index a50fc2e..08f925f 100644
+--- a/src/cmd/compile/internal/gc/builtin/runtime.go
++++ b/src/cmd/compile/internal/gc/builtin/runtime.go
+@@ -8,7 +8,7 @@
+
+ // +build ignore
+
+-package PACKAGE
++package runtime
+
+ // emitted by compiler, not referred to by go programs
+
+diff --git a/src/cmd/compile/internal/gc/builtin/unsafe.go b/src/cmd/compile/internal/gc/builtin/unsafe.go
+index ce50869..a7fc8aa 100644
+--- a/src/cmd/compile/internal/gc/builtin/unsafe.go
++++ b/src/cmd/compile/internal/gc/builtin/unsafe.go
+@@ -8,7 +8,7 @@
+
+ // +build ignore
+
+-package PACKAGE
++package unsafe
+
+ type Pointer uintptr // not really; filled in by compiler
+
+diff --git a/src/cmd/compile/internal/gc/builtin_test.go b/src/cmd/compile/internal/gc/builtin_test.go
+new file mode 100644
+index 0000000..94111e6
+--- /dev/null
++++ b/src/cmd/compile/internal/gc/builtin_test.go
+@@ -0,0 +1,31 @@
++// Copyright 2016 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++package gc_test
++
++import (
++ "bytes"
++ "internal/testenv"
++ "io/ioutil"
++ "os/exec"
++ "testing"
++)
++
++func TestBuiltin(t *testing.T) {
++ testenv.MustHaveGoRun(t)
++
++ old, err := ioutil.ReadFile("builtin.go")
++ if err != nil {
++ t.Fatal(err)
++ }
++
++ new, err := exec.Command("go", "run", "mkbuiltin.go", "-stdout").Output()
++ if err != nil {
++ t.Fatal(err)
++ }
++
++ if !bytes.Equal(old, new) {
++ t.Fatal("builtin.go out of date; run mkbuiltin.go")
++ }
++}
diff --git a/src/cmd/compile/internal/gc/cgen.go b/src/cmd/compile/internal/gc/cgen.go
-index 6456240..8855bac 100644
+index 6456240..5dc74ae 100644
--- a/src/cmd/compile/internal/gc/cgen.go
+++ b/src/cmd/compile/internal/gc/cgen.go
-@@ -252,7 +252,7 @@ func cgen_wb(n, res *Node, wb bool) {
+@@ -247,7 +247,7 @@ func cgen_wb(n, res *Node, wb bool) {
return
}
-- if Ctxt.Arch.Thechar == '0' || Ctxt.Arch.Thechar == '7' || Ctxt.Arch.Thechar == '9' {
-+ if Ctxt.Arch.Thechar == '0' || Ctxt.Arch.Thechar == '7' || Ctxt.Arch.Thechar == '9' || Ctxt.Arch.Thechar == 'z' {
- // if both are addressable, move
- if n.Addable {
- if n.Op == OREGISTER || res.Op == OREGISTER {
-@@ -752,14 +752,14 @@ abop: // asymmetric binary
- Regalloc(&n1, nl.Type, res)
- Cgen(nl, &n1)
-
-- if Smallintconst(nr) && Ctxt.Arch.Thechar != '0' && Ctxt.Arch.Thechar != '5' && Ctxt.Arch.Thechar != '7' && Ctxt.Arch.Thechar != '9' { // TODO(rsc): Check opcode for arm
-+ if Smallintconst(nr) && Ctxt.Arch.Thechar != '0' && Ctxt.Arch.Thechar != '5' && Ctxt.Arch.Thechar != '7' && Ctxt.Arch.Thechar != '9' && Ctxt.Arch.Thechar != 'z' { // TODO(rsc): Check opcode for arm
- n2 = *nr
- } else {
- Regalloc(&n2, nr.Type, nil)
- Cgen(nr, &n2)
- }
- } else {
-- if Smallintconst(nr) && Ctxt.Arch.Thechar != '0' && Ctxt.Arch.Thechar != '5' && Ctxt.Arch.Thechar != '7' && Ctxt.Arch.Thechar != '9' { // TODO(rsc): Check opcode for arm
-+ if Smallintconst(nr) && Ctxt.Arch.Thechar != '0' && Ctxt.Arch.Thechar != '5' && Ctxt.Arch.Thechar != '7' && Ctxt.Arch.Thechar != '9' && Ctxt.Arch.Thechar != 'z' { // TODO(rsc): Check opcode for arm
- n2 = *nr
- } else {
- Regalloc(&n2, nr.Type, res)
+- if (Ctxt.Arch.Thechar == '6' || Ctxt.Arch.Thechar == '8') && n.Addable {
++ if (Ctxt.Arch.Thechar == '6' || Ctxt.Arch.Thechar == '8' || Ctxt.Arch.Thechar == 'z') && n.Addable {
+ Thearch.Gmove(n, res)
+ return
+ }
@@ -1832,7 +1832,7 @@ func bgenx(n, res *Node, wantTrue bool, likely int, to *obj.Prog) {
// but they don't support direct generation of a bool value yet.
// We can fix that as we go.
@@ -9841,15 +10115,6 @@ index 6456240..8855bac 100644
// no need for a temporary
bgenNonZero(n, nil, wantTrue, likely, to)
return
-@@ -2026,7 +2026,7 @@ func bgenx(n, res *Node, wantTrue bool, likely int, to *obj.Prog) {
- Cgen(nl, &n1)
- nl = &n1
-
-- if Smallintconst(nr) && Ctxt.Arch.Thechar != '0' && Ctxt.Arch.Thechar != '9' {
-+ if Smallintconst(nr) && Ctxt.Arch.Thechar != '0' && Ctxt.Arch.Thechar != '9' && Ctxt.Arch.Thechar != 'z' {
- Thearch.Gins(Thearch.Optoas(OCMP, nr.Type), nl, nr)
- bins(nr.Type, res, op, likely, to)
- return
@@ -2640,7 +2640,7 @@ func cgen_div(op Op, nl *Node, nr *Node, res *Node) {
// in peep and optoas in order to enable this.
// TODO(rsc): ppc64 needs to support the relevant instructions
@@ -9859,11 +10124,82 @@ index 6456240..8855bac 100644
goto longdiv
}
w = int(nl.Type.Width * 8)
+diff --git a/src/cmd/compile/internal/gc/esc.go b/src/cmd/compile/internal/gc/esc.go
+index ff983e7..ccdb781 100644
+--- a/src/cmd/compile/internal/gc/esc.go
++++ b/src/cmd/compile/internal/gc/esc.go
+@@ -962,7 +962,7 @@ func escassign(e *EscState, dst *Node, src *Node) {
+ dst = &e.theSink
+ }
+
+- case ODOT: // treat "dst.x = src" as "dst = src"
++ case ODOT: // treat "dst.x = src" as "dst = src"
+ escassign(e, dst.Left, src)
+
+ return
+@@ -1042,7 +1042,6 @@ func escassign(e *EscState, dst *Node, src *Node) {
+ ODOTMETH,
+ // treat recv.meth as a value with recv in it, only happens in ODEFER and OPROC
+ // iface.method already leaks iface in esccall, no need to put in extra ODOTINTER edge here
+- ODOTTYPE,
+ ODOTTYPE2,
+ OSLICE,
+ OSLICE3,
+@@ -1052,6 +1051,12 @@ func escassign(e *EscState, dst *Node, src *Node) {
+ // Conversions, field access, slice all preserve the input value.
+ escassign(e, dst, src.Left)
+
++ case ODOTTYPE:
++ if src.Type != nil && !haspointers(src.Type) {
++ break
++ }
++ escassign(e, dst, src.Left)
++
+ case OAPPEND:
+ // Append returns first argument.
+ // Subsequent arguments are already leaked because they are operands to append.
+@@ -1549,9 +1554,9 @@ func escflows(e *EscState, dst *Node, src *Node) {
+ // finding an OADDR just means we're following the upstream of a dereference,
+ // so this address doesn't leak (yet).
+ // If level == 0, it means the /value/ of this node can reach the root of this flood.
+-// so if this node is an OADDR, it's argument should be marked as escaping iff
+-// it's currfn/e->loopdepth are different from the flood's root.
+-// Once an object has been moved to the heap, all of it's upstream should be considered
++// so if this node is an OADDR, its argument should be marked as escaping iff
++// its currfn/e->loopdepth are different from the flood's root.
++// Once an object has been moved to the heap, all of its upstream should be considered
+ // escaping to the global scope.
+ func escflood(e *EscState, dst *Node) {
+ switch dst.Op {
diff --git a/src/cmd/compile/internal/gc/go.go b/src/cmd/compile/internal/gc/go.go
-index 3146cae..d4fec64 100644
+index 3146cae..7c1f257 100644
--- a/src/cmd/compile/internal/gc/go.go
+++ b/src/cmd/compile/internal/gc/go.go
-@@ -493,6 +493,12 @@ var debugstr string
+@@ -386,15 +386,14 @@ type Sig struct {
+ }
+
+ type Io struct {
+- infile string
+- bin *obj.Biobuf
+- cp string // used for content when bin==nil
+- last int
+- peekc int
+- peekc1 int // second peekc for ...
+- nlsemi bool
+- eofnl bool
+- importsafe bool
++ infile string
++ bin *obj.Biobuf
++ cp string // used for content when bin==nil
++ last int
++ peekc int
++ peekc1 int // second peekc for ...
++ nlsemi bool
++ eofnl bool
+ }
+
+ type Dlist struct {
+@@ -493,6 +492,12 @@ var debugstr string
var Debug_checknil int
var Debug_typeassert int
@@ -9908,9 +10244,18 @@ index 30bf736..4a4d23e 100644
}
if a.Type != obj.TYPE_MEM {
diff --git a/src/cmd/compile/internal/gc/lex.go b/src/cmd/compile/internal/gc/lex.go
-index b9c2735..179ec97 100644
+index b9c2735..266e221 100644
--- a/src/cmd/compile/internal/gc/lex.go
+++ b/src/cmd/compile/internal/gc/lex.go
+@@ -2,7 +2,7 @@
+ // Use of this source code is governed by a BSD-style
+ // license that can be found in the LICENSE file.
+
+-//go:generate go run mkbuiltin.go runtime unsafe
++//go:generate go run mkbuiltin.go
+
+ package gc
+
@@ -178,12 +178,14 @@ func Main() {
obj.Flagcount("N", "disable optimizations", &Debug['N'])
obj.Flagcount("P", "debug peephole optimizer", &Debug['P'])
@@ -9954,6 +10299,201 @@ index b9c2735..179ec97 100644
flag.BoolVar(&flag_dynlink, "dynlink", false, "support references to Go symbols defined in other shared libraries")
}
obj.Flagstr("cpuprofile", "write cpu profile to `file`", &cpuprofile)
+@@ -884,7 +888,6 @@ func cannedimports(file string, cp string) {
+ curio.infile = file
+ curio.cp = cp
+ curio.nlsemi = false
+- curio.importsafe = false
+
+ typecheckok = true
+ incannedimport = 1
+diff --git a/src/cmd/compile/internal/gc/mkbuiltin.go b/src/cmd/compile/internal/gc/mkbuiltin.go
+index b1e4458..13cde5e 100644
+--- a/src/cmd/compile/internal/gc/mkbuiltin.go
++++ b/src/cmd/compile/internal/gc/mkbuiltin.go
+@@ -4,95 +4,90 @@
+
+ // +build ignore
+
+-// Generate builtin.go from builtin/runtime.go and builtin/unsafe.go
+-// (passed as arguments on the command line by a go:generate comment).
++// Generate builtin.go from builtin/runtime.go and builtin/unsafe.go.
+ // Run this after changing builtin/runtime.go and builtin/unsafe.go
+ // or after changing the export metadata format in the compiler.
+ // Either way, you need to have a working compiler binary first.
+ package main
+
+ import (
+- "bufio"
++ "bytes"
++ "flag"
+ "fmt"
+ "io"
++ "io/ioutil"
+ "log"
+ "os"
+ "os/exec"
+- "strings"
+ )
+
++var stdout = flag.Bool("stdout", false, "write to stdout instead of builtin.go")
++
+ func main() {
+- f, err := os.Create("builtin.go")
+- if err != nil {
+- log.Fatal(err)
+- }
+- defer f.Close()
+- w := bufio.NewWriter(f)
++ flag.Parse()
+
+- fmt.Fprintln(w, "// AUTO-GENERATED by mkbuiltin.go; DO NOT EDIT")
+- fmt.Fprintln(w, "")
+- fmt.Fprintln(w, "package gc")
++ var b bytes.Buffer
++ fmt.Fprintln(&b, "// AUTO-GENERATED by mkbuiltin.go; DO NOT EDIT")
++ fmt.Fprintln(&b, "")
++ fmt.Fprintln(&b, "package gc")
+
+- for _, name := range os.Args[1:] {
+- mkbuiltin(w, name)
+- }
++ mkbuiltin(&b, "runtime")
++ mkbuiltin(&b, "unsafe")
+
+- if err := w.Flush(); err != nil {
++ var err error
++ if *stdout {
++ _, err = os.Stdout.Write(b.Bytes())
++ } else {
++ err = ioutil.WriteFile("builtin.go", b.Bytes(), 0666)
++ }
++ if err != nil {
+ log.Fatal(err)
+ }
+ }
+
+-// Compile .go file, import data from .6 file, and write Go string version.
++// Compile .go file, import data from .o file, and write Go string version.
+ func mkbuiltin(w io.Writer, name string) {
+- if err := exec.Command("go", "tool", "compile", "-A", "builtin/"+name+".go").Run(); err != nil {
++ args := []string{"tool", "compile", "-A"}
++ if name == "runtime" {
++ args = append(args, "-u")
++ }
++ args = append(args, "builtin/"+name+".go")
++
++ if err := exec.Command("go", args...).Run(); err != nil {
+ log.Fatal(err)
+ }
+ obj := name + ".o"
+ defer os.Remove(obj)
+
+- r, err := os.Open(obj)
++ b, err := ioutil.ReadFile(obj)
+ if err != nil {
+ log.Fatal(err)
+ }
+- defer r.Close()
+- scanner := bufio.NewScanner(r)
+
+ // Look for $$ that introduces imports.
+- for scanner.Scan() {
+- if strings.Contains(scanner.Text(), "$$") {
+- goto Begin
+- }
++ i := bytes.Index(b, []byte("\n$$\n"))
++ if i < 0 {
++ log.Fatal("did not find beginning of imports")
+ }
+- log.Fatal("did not find beginning of imports")
+-
+-Begin:
+- initfunc := fmt.Sprintf("init_%s_function", name)
+-
+- fmt.Fprintf(w, "\nconst %simport = \"\" +\n", name)
+-
+- // sys.go claims to be in package PACKAGE to avoid
+- // conflicts during "go tool compile sys.go". Rename PACKAGE to $2.
+- replacer := strings.NewReplacer("PACKAGE", name)
++ i += 4
+
+- // Process imports, stopping at $$ that closes them.
+- for scanner.Scan() {
+- p := scanner.Text()
+- if strings.Contains(p, "$$") {
+- goto End
+- }
++ // Look for $$ that closes imports.
++ j := bytes.Index(b[i:], []byte("\n$$\n"))
++ if j < 0 {
++ log.Fatal("did not find end of imports")
++ }
++ j += i + 4
+
++ // Process and reformat imports.
++ fmt.Fprintf(w, "\nconst %simport = \"\"", name)
++ for _, p := range bytes.SplitAfter(b[i:j], []byte("\n")) {
+ // Chop leading white space.
+- p = strings.TrimLeft(p, " \t")
+-
+- // Cut out decl of init_$1_function - it doesn't exist.
+- if strings.Contains(p, initfunc) {
++ p = bytes.TrimLeft(p, " \t")
++ if len(p) == 0 {
+ continue
+ }
+
+- fmt.Fprintf(w, "\t%q +\n", replacer.Replace(p)+"\n")
++ fmt.Fprintf(w, " +\n\t%q", p)
+ }
+- log.Fatal("did not find end of imports")
+-
+-End:
+- fmt.Fprintf(w, "\t\"$$\\n\"\n")
++ fmt.Fprintf(w, "\n")
+ }
+diff --git a/src/cmd/compile/internal/gc/parser.go b/src/cmd/compile/internal/gc/parser.go
+index 054cf73..dc6ae72 100644
+--- a/src/cmd/compile/internal/gc/parser.go
++++ b/src/cmd/compile/internal/gc/parser.go
+@@ -67,11 +67,10 @@ func (p *parser) loadsys() {
+ importpkg = Runtimepkg
+
+ if Debug['A'] != 0 {
+- cannedimports("runtime.Builtin", "package runtime\n\n$$\n\n")
++ cannedimports("runtime.Builtin", "package runtime safe\n\n$$\n\n")
+ } else {
+ cannedimports("runtime.Builtin", runtimeimport)
+ }
+- curio.importsafe = true
+
+ p.import_package()
+ p.import_there()
+@@ -467,9 +466,10 @@ func (p *parser) import_package() {
+ p.import_error()
+ }
+
++ importsafe := false
+ if p.tok == LNAME {
+ if p.sym_.Name == "safe" {
+- curio.importsafe = true
++ importsafe = true
+ }
+ p.next()
+ }
+@@ -484,9 +484,9 @@ func (p *parser) import_package() {
+ if incannedimport == 0 {
+ importpkg.Direct = true
+ }
+- importpkg.Safe = curio.importsafe
++ importpkg.Safe = importsafe
+
+- if safemode != 0 && !curio.importsafe {
++ if safemode != 0 && !importsafe {
+ Yyerror("cannot import unsafe package %q", importpkg.Path)
+ }
+ }
diff --git a/src/cmd/compile/internal/gc/pgen.go b/src/cmd/compile/internal/gc/pgen.go
index ffc0ab9..de153b4 100644
--- a/src/cmd/compile/internal/gc/pgen.go
@@ -10007,6 +10547,18 @@ index 14dc03b..ae54c26 100644
Fatalf("regopt not implemented for from3")
}
+diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go
+index f74bb33..8fd6f85 100644
+--- a/src/cmd/compile/internal/gc/typecheck.go
++++ b/src/cmd/compile/internal/gc/typecheck.go
+@@ -936,7 +936,6 @@ OpSwitch:
+ n.Type = n.Right.Type
+ n.Right = nil
+ if n.Type == nil {
+- n.Type = nil
+ return
+ }
+ }
diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go
index e008317..0335138 100644
--- a/src/cmd/compile/internal/gc/walk.go
@@ -10316,10 +10868,10 @@ index 0000000..a1298a2
+}
diff --git a/src/cmd/compile/internal/s390x/ggen.go b/src/cmd/compile/internal/s390x/ggen.go
new file mode 100644
-index 0000000..756f193
+index 0000000..6e06bef
--- /dev/null
+++ b/src/cmd/compile/internal/s390x/ggen.go
-@@ -0,0 +1,611 @@
+@@ -0,0 +1,584 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
@@ -10855,8 +11407,6 @@ index 0000000..756f193
+// Called after regopt and peep have run.
+// Expand CHECKNIL pseudo-op into actual nil pointer check.
+func expandchecks(firstp *obj.Prog) {
-+ var p1 *obj.Prog
-+ var p2 *obj.Prog
+ for p := (*obj.Prog)(firstp); p != nil; p = p.Link {
+ if gc.Debug_checknil != 0 && gc.Ctxt.Debugvlog != 0 {
+ fmt.Printf("expandchecks: %v\n", p)
@@ -10871,57 +11421,32 @@ index 0000000..756f193
+ gc.Fatalf("invalid nil check %v\n", p)
+ }
+
-+ /*
-+ // check is
-+ // TD $4, R0, arg (R0 is always zero)
-+ // eqv. to:
-+ // tdeq r0, arg
-+ // NOTE: this needs special runtime support to make SIGTRAP recoverable.
-+ reg = p->from.reg;
-+ p->as = ATD;
-+ p->from = p->to = p->from3 = zprog.from;
-+ p->from.type = TYPE_CONST;
-+ p->from.offset = 4;
-+ p->from.reg = 0;
-+ p->reg = REGZERO;
-+ p->to.type = TYPE_REG;
-+ p->to.reg = reg;
-+ */
+ // check is
-+ // CMP arg, $0
-+ // BNE 2(PC) [likely]
-+ // MOVD R0, 0(R0)
-+ p1 = gc.Ctxt.NewProg()
++ // CMPBNE arg, $0, 2(PC) [likely]
++ // MOVD R0, 0(R0)
++ p1 := gc.Ctxt.NewProg()
+
-+ p2 = gc.Ctxt.NewProg()
+ gc.Clearp(p1)
-+ gc.Clearp(p2)
-+ p1.Link = p2
-+ p2.Link = p.Link
++ p1.Link = p.Link
+ p.Link = p1
+ p1.Lineno = p.Lineno
-+ p2.Lineno = p.Lineno
+ p1.Pc = 9999
-+ p2.Pc = 9999
-+ p.As = s390x.ACMP
-+ p.To.Type = obj.TYPE_CONST
-+ p.To.Offset = 0
-+ p1.As = s390x.ABNE
-+
-+ //p1->from.type = TYPE_CONST;
-+ //p1->from.offset = 1; // likely
-+ p1.To.Type = obj.TYPE_BRANCH
++ p.As = s390x.ACMPBNE
++ p.From3 = new(obj.Addr)
++ p.From3.Type = obj.TYPE_CONST
++ p.From3.Offset = 0
+
-+ p1.To.Val = p2.Link
++ p.To.Type = obj.TYPE_BRANCH
++ p.To.Val = p1.Link
+
+ // crash by write to memory address 0.
-+ p2.As = s390x.AMOVD
++ p1.As = s390x.AMOVD
+
-+ p2.From.Type = obj.TYPE_REG
-+ p2.From.Reg = s390x.REGZERO
-+ p2.To.Type = obj.TYPE_MEM
-+ p2.To.Reg = s390x.REGZERO
-+ p2.To.Offset = 0
++ p1.From.Type = obj.TYPE_REG
++ p1.From.Reg = s390x.REGZERO
++ p1.To.Type = obj.TYPE_MEM
++ p1.To.Reg = s390x.REGZERO
++ p1.To.Offset = 0
+ }
+}
+
@@ -10933,10 +11458,10 @@ index 0000000..756f193
+}
diff --git a/src/cmd/compile/internal/s390x/gsubr.go b/src/cmd/compile/internal/s390x/gsubr.go
new file mode 100644
-index 0000000..00e2059
+index 0000000..52cd5a2
--- /dev/null
+++ b/src/cmd/compile/internal/s390x/gsubr.go
-@@ -0,0 +1,972 @@
+@@ -0,0 +1,1115 @@
+// Derived from Inferno utils/6c/txt.c
+// http://code.google.com/p/inferno-os/source/browse/utils/6c/txt.c
+//
@@ -10978,11 +11503,13 @@ index 0000000..00e2059
+)
+
+var resvd = []int{
-+ s390x.REGZERO,
-+ s390x.REGSP, // reserved for SP
-+ s390x.REGG,
-+ s390x.REGTMP,
-+ s390x.REGTMP2,
++ s390x.REGZERO, // R0
++ s390x.REGTMP, // R10
++ s390x.REGTMP2, // R11
++ s390x.REGCTXT, // R12
++ s390x.REGG, // R13
++ s390x.REG_LR, // R14
++ s390x.REGSP, // R15
+}
+
+// generate
@@ -11105,11 +11632,11 @@ index 0000000..00e2059
+ return false
+ }
+
-+ if f.Xoffset < 0 || f.Xoffset >= 4096 {
++ if f.Xoffset < 0 || f.Xoffset >= 4096-8 {
+ return false
+ }
+
-+ if t.Xoffset < 0 || t.Xoffset >= 4096 {
++ if t.Xoffset < 0 || t.Xoffset >= 4096-8 {
+ return false
+ }
+
@@ -11185,6 +11712,11 @@ index 0000000..00e2059
+ goto hard
+ }
+ }
++
++ // immediate moves to memory have a 12-bit unsigned displacement
++ if t.Xoffset < 0 || t.Xoffset >= 4096-8 {
++ goto hard
++ }
+ }
+ }
+
@@ -11431,7 +11963,7 @@ index 0000000..00e2059
+ goto rdst
+
+ case gc.TFLOAT64<<16 | gc.TFLOAT32:
-+ a = s390x.AFRSP
++ a = s390x.ALEDBR
+ goto rdst
+ }
+
@@ -11477,16 +12009,18 @@ index 0000000..00e2059
+// It synthesizes some multiple-instruction sequences
+// so the front end can stay simpler.
+func gins(as int, f, t *gc.Node) *obj.Prog {
-+ if as >= obj.A_ARCHSPECIFIC {
-+ if x, ok := intLiteral(f); ok {
-+ ginscon(as, x, t)
-+ return nil // caller must not use
++ if t != nil {
++ if as >= obj.A_ARCHSPECIFIC {
++ if x, ok := intLiteral(f); ok {
++ ginscon(as, x, t)
++ return nil // caller must not use
++ }
+ }
-+ }
-+ if as == s390x.ACMP || as == s390x.ACMPU {
-+ if x, ok := intLiteral(t); ok {
-+ ginscon2(as, f, x)
-+ return nil // caller must not use
++ if as == s390x.ACMP || as == s390x.ACMPU {
++ if x, ok := intLiteral(t); ok {
++ ginscon2(as, f, x)
++ return nil // caller must not use
++ }
+ }
+ }
+ return rawgins(as, f, t)
@@ -11503,7 +12037,7 @@ index 0000000..00e2059
+
+ switch as {
+ // Bad things the front end has done to us. Crash to find call stack.
-+ case s390x.AAND, s390x.AMULLD:
++ case s390x.AMULLD:
+ if p.From.Type == obj.TYPE_CONST {
+ gc.Debug['h'] = 1
+ gc.Fatalf("bad inst: %v", p)
@@ -11885,36 +12419,170 @@ index 0000000..00e2059
+ OAddable = 1 << 1
+)
+
-+func xgen(n *gc.Node, a *gc.Node, o int) bool {
-+ // TODO(mundaym)
-+ return -1 != 0
-+}
++var clean [20]gc.Node
++
++var cleani int = 0
+
+func sudoclean() {
-+ return
++ if clean[cleani-1].Op != gc.OEMPTY {
++ gc.Regfree(&clean[cleani-1])
++ }
++ if clean[cleani-2].Op != gc.OEMPTY {
++ gc.Regfree(&clean[cleani-2])
++ }
++ cleani -= 2
+}
+
-+// generate code to compute address of n,
-+// a reference to a (perhaps nested) field inside
-+// an array or struct.
-+// return 0 on failure, 1 on success.
-+// on success, leaves usable address in a.
-+//
-+// caller is responsible for calling sudoclean
-+// after successful sudoaddable,
-+// to release the register used for a.
++/*
++ * generate code to compute address of n,
++ * a reference to a (perhaps nested) field inside
++ * an array or struct.
++ * return 0 on failure, 1 on success.
++ * on success, leaves usable address in a.
++ *
++ * caller is responsible for calling sudoclean
++ * after successful sudoaddable,
++ * to release the register used for a.
++ */
+func sudoaddable(as int, n *gc.Node, a *obj.Addr) bool {
-+ // TODO(mundaym)
++ if n.Type == nil {
++ return false
++ }
+
+ *a = obj.Addr{}
++
++ switch n.Op {
++ case gc.OLITERAL:
++ if !gc.Isconst(n, gc.CTINT) {
++ return false
++ }
++ v := n.Int()
++ switch as {
++ default:
++ return false
++
++ // operations that can cope with a 32-bit immediate
++ // TODO(mundaym): logical operations can work on high bits
++ case s390x.AADD,
++ s390x.AADDC,
++ s390x.ASUB,
++ s390x.AMULLW,
++ s390x.AAND,
++ s390x.AOR,
++ s390x.AXOR,
++ s390x.ASLD,
++ s390x.ASLW,
++ s390x.ASRAW,
++ s390x.ASRAD,
++ s390x.ASRW,
++ s390x.ASRD,
++ s390x.AMOVB,
++ s390x.AMOVBZ,
++ s390x.AMOVH,
++ s390x.AMOVHZ,
++ s390x.AMOVW,
++ s390x.AMOVWZ,
++ s390x.AMOVD:
++ if int64(int32(v)) != v {
++ return false
++ }
++
++ // for comparisons avoid immediates unless they can
++ // fit into a int8/uint8
++ // this favours combined compare and branch instructions
++ case s390x.ACMP:
++ if int64(int8(v)) != v {
++ return false
++ }
++ case s390x.ACMPU:
++ if int64(uint8(v)) != v {
++ return false
++ }
++ }
++
++ cleani += 2
++ reg := &clean[cleani-1]
++ reg1 := &clean[cleani-2]
++ reg.Op = gc.OEMPTY
++ reg1.Op = gc.OEMPTY
++ gc.Naddr(a, n)
++ return true
++
++ case gc.ODOT,
++ gc.ODOTPTR:
++ cleani += 2
++ reg := &clean[cleani-1]
++ reg1 := &clean[cleani-2]
++ reg.Op = gc.OEMPTY
++ reg1.Op = gc.OEMPTY
++ var nn *gc.Node
++ var oary [10]int64
++ o := gc.Dotoffset(n, oary[:], &nn)
++ if nn == nil {
++ sudoclean()
++ return false
++ }
++
++ if nn.Addable && o == 1 && oary[0] >= 0 {
++ // directly addressable set of DOTs
++ n1 := *nn
++
++ n1.Type = n.Type
++ n1.Xoffset += oary[0]
++ // check that the offset fits into a 12-bit displacement
++ if n1.Xoffset < 0 || n1.Xoffset >= (1<<12)-8 {
++ sudoclean()
++ return false
++ }
++ gc.Naddr(a, &n1)
++ return true
++ }
++
++ gc.Regalloc(reg, gc.Types[gc.Tptr], nil)
++ n1 := *reg
++ n1.Op = gc.OINDREG
++ if oary[0] >= 0 {
++ gc.Agen(nn, reg)
++ n1.Xoffset = oary[0]
++ } else {
++ gc.Cgen(nn, reg)
++ gc.Cgen_checknil(reg)
++ n1.Xoffset = -(oary[0] + 1)
++ }
++
++ for i := 1; i < o; i++ {
++ if oary[i] >= 0 {
++ gc.Fatalf("can't happen")
++ }
++ gins(s390x.AMOVD, &n1, reg)
++ gc.Cgen_checknil(reg)
++ n1.Xoffset = -(oary[i] + 1)
++ }
++
++ a.Type = obj.TYPE_NONE
++ a.Index = obj.TYPE_NONE
++ // check that the offset fits into a 12-bit displacement
++ if n1.Xoffset < 0 || n1.Xoffset >= (1<<12)-8 {
++ tmp := n1
++ tmp.Op = gc.OREGISTER
++ tmp.Type = gc.Types[gc.Tptr]
++ tmp.Xoffset = 0
++ gc.Cgen_checknil(&tmp)
++ ginscon(s390x.AADD, n1.Xoffset, &tmp)
++ n1.Xoffset = 0
++ }
++ gc.Naddr(a, &n1)
++ return true
++ }
++
+ return false
+}
diff --git a/src/cmd/compile/internal/s390x/peep.go b/src/cmd/compile/internal/s390x/peep.go
new file mode 100644
-index 0000000..c49ebca
+index 0000000..343364a
--- /dev/null
+++ b/src/cmd/compile/internal/s390x/peep.go
-@@ -0,0 +1,1419 @@
+@@ -0,0 +1,1819 @@
+// Derived from Inferno utils/6c/peep.c
+// http://code.google.com/p/inferno-os/source/browse/utils/6c/peep.c
+//
@@ -11966,14 +12634,21 @@ index 0000000..c49ebca
+ }
+ gactive = 0
+
-+ var p *obj.Prog
++ // promote zero moves to MOVD so that they are more likely to
++ // be optimized in later passes
++ for r := (*gc.Flow)(g.Start); r != nil; r = r.Link {
++ p := r.Prog
++ if isMove(p) && p.As != s390x.AMOVD && regzer(&p.From) != 0 && isGPR(&p.To) {
++ p.As = s390x.AMOVD
++ }
++ }
+
+ // constant propagation
+ // find MOV $con,R followed by
+ // another MOV $con,R without
+ // setting R in the interim
+ for r := (*gc.Flow)(g.Start); r != nil; r = r.Link {
-+ p = r.Prog
++ p := r.Prog
+ switch p.As {
+ case s390x.AMOVD,
+ s390x.AMOVW, s390x.AMOVWZ,
@@ -11988,59 +12663,39 @@ index 0000000..c49ebca
+ }
+ }
+
-+ var r *gc.Flow
-+ var t int
-+loop1:
-+ // if gc.Debug['P'] != 0 && gc.Debug['v'] != 0 {
-+ // gc.Dumpit("loop1", g.Start, 0)
-+ // }
-+
-+ t = 0
-+ for r = g.Start; r != nil; r = r.Link {
-+ p = r.Prog
++ for {
++ changed := false
++ for r := (*gc.Flow)(g.Start); r != nil; r = r.Link {
++ p := r.Prog
++
++ // TODO(austin) Handle smaller moves. arm and amd64
++ // distinguish between moves that moves that *must*
++ // sign/zero extend and moves that don't care so they
++ // can eliminate moves that don't care without
++ // breaking moves that do care. This might let us
++ // simplify or remove the next peep loop, too.
++ if p.As == s390x.AMOVD || p.As == s390x.AFMOVD {
++ if regtyp(&p.To) {
++ // Convert uses to $0 to uses of R0 and
++ // propagate R0
++ if p.As == s390x.AMOVD && regzer(&p.From) != 0 {
++ p.From.Type = obj.TYPE_REG
++ p.From.Reg = s390x.REGZERO
++ }
+
-+ // TODO(austin) Handle smaller moves. arm and amd64
-+ // distinguish between moves that moves that *must*
-+ // sign/zero extend and moves that don't care so they
-+ // can eliminate moves that don't care without
-+ // breaking moves that do care. This might let us
-+ // simplify or remove the next peep loop, too.
-+ if p.As == s390x.AMOVD || p.As == s390x.AFMOVD {
-+ if regtyp(&p.To) {
-+ // Try to eliminate reg->reg moves
-+ if regtyp(&p.From) {
-+ if p.From.Type == p.To.Type {
-+ if copyprop(r) {
++ // Try to eliminate reg->reg moves
++ if isGPR(&p.From) || isFPR(&p.From) {
++ if copyprop(r) || (subprop(r) && copyprop(r)) {
+ excise(r)
-+ t++
-+ } else if subprop(r) && copyprop(r) {
-+ excise(r)
-+ t++
-+ }
-+ }
-+ }
-+
-+ // Convert uses to $0 to uses of R0 and
-+ // propagate R0
-+ if regzer(&p.From) != 0 {
-+ if p.To.Type == obj.TYPE_REG {
-+ p.From.Type = obj.TYPE_REG
-+ p.From.Reg = s390x.REGZERO
-+ if copyprop(r) {
-+ excise(r)
-+ t++
-+ } else if subprop(r) && copyprop(r) {
-+ excise(r)
-+ t++
++ changed = true
+ }
+ }
+ }
+ }
+ }
-+ }
-+
-+ if t != 0 {
-+ goto loop1
++ if !changed {
++ break
++ }
+ }
+
+ if gc.Debug['P'] != 0 && gc.Debug['v'] != 0 {
@@ -12053,12 +12708,11 @@ index 0000000..c49ebca
+ */
+
+ for r := (*gc.Flow)(g.Start); r != nil; r = r.Link {
-+
+ if (gc.Debugmovprop != -1) && (movprop_cnt >= gc.Debugmovprop) {
+ break
+ }
+
-+ p = r.Prog
++ p := r.Prog
+
+ switch p.As {
+ case s390x.AFMOVS,
@@ -12095,7 +12749,6 @@ index 0000000..c49ebca
+
+ for ; ; r1 = gc.Uniqs(r1) {
+ var p1 *obj.Prog
-+ var t int
+
+ if r1 == nil || r1 == r0 {
+ break
@@ -12117,7 +12770,7 @@ index 0000000..c49ebca
+ p1.From = p0.From
+ movprop_cnt += 1
+ } else {
-+ t = copyu(p1, v0, nil)
++ t := copyu(p1, v0, nil)
+ if gc.Debug['D'] != 0 {
+ fmt.Printf("try v0 mov prop t=%d\n", t)
+ fmt.Printf("%v\n", p0)
@@ -12174,10 +12827,8 @@ index 0000000..c49ebca
+ /*
+ * look for MOVB x,R; MOVB R,R (for small MOVs not handled above)
+ */
-+ var p1 *obj.Prog
-+ var r1 *gc.Flow
+ for r := (*gc.Flow)(g.Start); r != nil; r = r.Link {
-+ p = r.Prog
++ p := r.Prog
+ switch p.As {
+ default:
+ continue
@@ -12193,11 +12844,11 @@ index 0000000..c49ebca
+ }
+ }
+
-+ r1 = r.Link
++ r1 := r.Link
+ if r1 == nil {
+ continue
+ }
-+ p1 = r1.Prog
++ p1 := r1.Prog
+ if p1.As != p.As {
+ continue
+ }
@@ -12210,6 +12861,18 @@ index 0000000..c49ebca
+ excise(r1)
+ }
+
++ // Remove redundant moves/casts
++ fuseMoveChains(g.Start)
++ if gc.Debug['P'] != 0 && gc.Debug['v'] != 0 {
++ gc.Dumpit("fuse move chains", g.Start, 0)
++ }
++
++ // Fuse memory zeroing instructions into XC instructions
++ fuseClear(g.Start)
++ if gc.Debug['P'] != 0 && gc.Debug['v'] != 0 {
++ gc.Dumpit("fuse clears", g.Start, 0)
++ }
++
+ if gc.Debug['P'] > 1 {
+ goto ret /* allow following code improvement to be suppressed */
+ }
@@ -12219,7 +12882,7 @@ index 0000000..c49ebca
+ // push any load from memory as early as possible
+ // to give it time to complete before use.
+ for r := (*gc.Flow)(g.Start); r != nil; r = r.Link {
-+ p = r.Prog
++ p := r.Prog
+ switch p.As {
+ case s390x.AMOVB,
+ s390x.AMOVW,
@@ -12246,7 +12909,7 @@ index 0000000..c49ebca
+ break
+ }
+
-+ p = r.Prog
++ p := r.Prog
+
+ switch p.As {
+ case s390x.AADD,
@@ -12309,10 +12972,7 @@ index 0000000..c49ebca
+
+ p1 := r1.Prog
+ switch p1.As {
-+ case s390x.AMOVD,
-+ s390x.AMOVW, s390x.AMOVWZ,
-+ s390x.AMOVH, s390x.AMOVHZ,
-+ s390x.AMOVB, s390x.AMOVBZ:
++ case s390x.AMOVD:
+ if p1.To.Type != obj.TYPE_REG {
+ continue
+ }
@@ -12347,30 +13007,31 @@ index 0000000..c49ebca
+ if (gc.Debugcnb != -1) && (cnb_cnt >= gc.Debugcnb) {
+ break
+ }
-+ p = r.Prog
-+ r1 = gc.Uniqs(r)
++ p := r.Prog
++ r1 := gc.Uniqs(r)
+ if r1 == nil {
+ continue
+ }
-+ p1 = r1.Prog
++ p1 := r1.Prog
+
++ var ins int16
+ switch p.As {
+ case s390x.ACMP:
+ switch p1.As {
+ case s390x.ABCL, s390x.ABC:
+ continue
+ case s390x.ABEQ:
-+ t = s390x.ACMPBEQ
++ ins = s390x.ACMPBEQ
+ case s390x.ABGE:
-+ t = s390x.ACMPBGE
++ ins = s390x.ACMPBGE
+ case s390x.ABGT:
-+ t = s390x.ACMPBGT
++ ins = s390x.ACMPBGT
+ case s390x.ABLE:
-+ t = s390x.ACMPBLE
++ ins = s390x.ACMPBLE
+ case s390x.ABLT:
-+ t = s390x.ACMPBLT
++ ins = s390x.ACMPBLT
+ case s390x.ABNE:
-+ t = s390x.ACMPBNE
++ ins = s390x.ACMPBNE
+ default:
+ continue
+ }
@@ -12380,17 +13041,17 @@ index 0000000..c49ebca
+ case s390x.ABCL, s390x.ABC:
+ continue
+ case s390x.ABEQ:
-+ t = s390x.ACMPUBEQ
++ ins = s390x.ACMPUBEQ
+ case s390x.ABGE:
-+ t = s390x.ACMPUBGE
++ ins = s390x.ACMPUBGE
+ case s390x.ABGT:
-+ t = s390x.ACMPUBGT
++ ins = s390x.ACMPUBGT
+ case s390x.ABLE:
-+ t = s390x.ACMPUBLE
++ ins = s390x.ACMPUBLE
+ case s390x.ABLT:
-+ t = s390x.ACMPUBLT
++ ins = s390x.ACMPUBLT
+ case s390x.ABNE:
-+ t = s390x.ACMPUBNE
++ ins = s390x.ACMPUBNE
+ default:
+ continue
+ }
@@ -12411,7 +13072,7 @@ index 0000000..c49ebca
+ }
+
+ if p.To.Type == obj.TYPE_REG {
-+ p1.As = int16(t)
++ p1.As = ins
+ p1.From = p.From
+ p1.Reg = p.To.Reg
+ p1.From3 = nil
@@ -12427,7 +13088,7 @@ index 0000000..c49ebca
+ }
+ default:
+ }
-+ p1.As = int16(t)
++ p1.As = ins
+ p1.From = p.From
+ p1.Reg = 0
+ p1.From3 = new(obj.Addr)
@@ -12447,46 +13108,45 @@ index 0000000..c49ebca
+ gc.Dumpit("compare and branch", g.Start, 0)
+ }
+
++ // Fuse LOAD/STORE instructions into LOAD/STORE MULTIPLE instructions
++ fuseMultiple(g.Start)
++ if gc.Debug['P'] != 0 && gc.Debug['v'] != 0 {
++ gc.Dumpit("pass 7 fuse load/store instructions", g.Start, 0)
++ }
++
+ret:
+ gc.Flowend(g)
+}
+
+func conprop(r0 *gc.Flow) {
-+ var p *obj.Prog
-+ var t int
-+
+ p0 := (*obj.Prog)(r0.Prog)
+ v0 := (*obj.Addr)(&p0.To)
+ r := (*gc.Flow)(r0)
++ for {
++ r = gc.Uniqs(r)
++ if r == nil || r == r0 {
++ return
++ }
++ if gc.Uniqp(r) == nil {
++ return
++ }
+
-+loop:
-+ r = gc.Uniqs(r)
-+ if r == nil || r == r0 {
-+ return
-+ }
-+ if gc.Uniqp(r) == nil {
-+ return
-+ }
-+
-+ p = r.Prog
-+ t = copyu(p, v0, nil)
-+ switch t {
-+ case 0, // miss
-+ 1: // use
-+ goto loop
-+
-+ case 2, // rar
-+ 4: // use and set
-+ break
-+
-+ case 3: // set
-+ if p.As == p0.As && p.From.Type == p0.From.Type && p.From.Reg == p0.From.Reg && p.From.Node == p0.From.Node &&
-+ p.From.Offset == p0.From.Offset && p.From.Scale == p0.From.Scale && p.From.Index == p0.From.Index {
-+ if p.From.Val == p0.From.Val {
-+ excise(r)
-+ goto loop
++ p := r.Prog
++ t := copyu(p, v0, nil)
++ switch t {
++ case 0, // miss
++ 1: // use
++ continue
++ case 3: // set
++ if p.As == p0.As && p.From.Type == p0.From.Type && p.From.Reg == p0.From.Reg && p.From.Node == p0.From.Node &&
++ p.From.Offset == p0.From.Offset && p.From.Scale == p0.From.Scale && p.From.Index == p0.From.Index {
++ if p.From.Val == p0.From.Val {
++ excise(r)
++ continue
++ }
+ }
+ }
++ break
+ }
+}
+
@@ -12508,12 +13168,11 @@ index 0000000..c49ebca
+
+func pushback(r0 *gc.Flow) {
+ var r *gc.Flow
-+ var p *obj.Prog
+
+ var b *gc.Flow
+ p0 := (*obj.Prog)(r0.Prog)
+ for r = gc.Uniqp(r0); r != nil && gc.Uniqs(r) != nil; r = gc.Uniqp(r) {
-+ p = r.Prog
++ p := r.Prog
+ if p.As != obj.ANOP {
+ if !regconsttyp(&p.From) || !regtyp(&p.To) {
+ break
@@ -12553,7 +13212,7 @@ index 0000000..c49ebca
+ t := obj.Prog(*r0.Prog)
+ for r = gc.Uniqp(r0); ; r = gc.Uniqp(r) {
+ p0 = r.Link.Prog
-+ p = r.Prog
++ p := r.Prog
+ p0.As = p.As
+ p0.Lineno = p.Lineno
+ p0.From = p.From
@@ -12619,6 +13278,33 @@ index 0000000..c49ebca
+ return a.Type == obj.TYPE_REG && s390x.REG_R0 <= a.Reg && a.Reg <= s390x.REG_F15 && a.Reg != s390x.REGZERO
+}
+
++// isGPR returns true if a refers to a general purpose register (GPR).
++// R0/REGZERO is treated as a GPR.
++func isGPR(a *obj.Addr) bool {
++ return a.Type == obj.TYPE_REG &&
++ s390x.REG_R0 <= a.Reg &&
++ a.Reg <= s390x.REG_R15
++}
++
++func isFPR(a *obj.Addr) bool {
++ return a.Type == obj.TYPE_REG &&
++ s390x.REG_F0 <= a.Reg &&
++ a.Reg <= s390x.REG_F15
++}
++
++// isIndirectMem returns true if a refers to a memory location addressable by a
++// register and an offset, such as:
++// x+8(R1)
++// and
++// 0(R10)
++// It returns false if the address contains an index register such as:
++// 16(R1)(R2*1)
++func isIndirectMem(a *obj.Addr) bool {
++ return a.Type == obj.TYPE_MEM &&
++ a.Index == 0 &&
++ (a.Name == obj.NAME_NONE || a.Name == obj.NAME_AUTO || a.Name == obj.NAME_PARAM)
++}
++
+/*
+ * the idea is to substitute
+ * one register for another
@@ -12855,7 +13541,7 @@ index 0000000..c49ebca
+ fmt.Printf("copyu: can't find %v\n", obj.Aconv(int(p.As)))
+ return 2
+
-+ case obj.ANOP, /* read p->from, write p->to */
++ case /* read p->from, write p->to */
+ s390x.AMOVH,
+ s390x.AMOVHZ,
+ s390x.AMOVB,
@@ -12870,7 +13556,7 @@ index 0000000..c49ebca
+ s390x.ASUBZE,
+ s390x.AFMOVS,
+ s390x.AFMOVD,
-+ s390x.AFRSP,
++ s390x.ALEDBR,
+ s390x.AFNEG,
+ s390x.ALDEBR,
+ s390x.ACLFEBR,
@@ -13067,7 +13753,7 @@ index 0000000..c49ebca
+ }
+ return 0
+
-+ case obj.ARET:
++ case obj.ARET, obj.AUNDEF:
+ if s != nil {
+ return 0
+ }
@@ -13123,7 +13809,8 @@ index 0000000..c49ebca
+ obj.AVARDEF,
+ obj.AVARKILL,
+ obj.AVARLIVE,
-+ obj.AUSEFIELD:
++ obj.AUSEFIELD,
++ obj.ANOP:
+ return 0
+ }
+}
@@ -13334,9 +14021,390 @@ index 0000000..c49ebca
+ }
+ return false
+}
++
++func isMove(p *obj.Prog) bool {
++ switch p.As {
++ case s390x.AMOVD,
++ s390x.AMOVW, s390x.AMOVWZ,
++ s390x.AMOVH, s390x.AMOVHZ,
++ s390x.AMOVB, s390x.AMOVBZ,
++ s390x.AFMOVD, s390x.AFMOVS:
++ return true
++ }
++ return false
++}
++
++// fuseMoveChains looks to see if destination register is used
++// again and if not merges the moves.
++//
++// Look for this pattern (sequence of moves):
++// MOVB $17, R1
++// MOVBZ R1, R1
++// Replace with:
++// MOVBZ $17, R1
++func fuseMoveChains(r *gc.Flow) {
++ for ; r != nil; r = r.Link {
++ p := r.Prog
++ if !isMove(p) || !isGPR(&p.To) {
++ continue
++ }
++
++ // r is a move with a destination register
++ var move *gc.Flow
++ visited := make(map[*gc.Flow]bool)
++ for rr := gc.Uniqs(r); rr != nil; rr = gc.Uniqs(rr) {
++ if visited[rr] {
++ break
++ } else {
++ visited[rr] = true
++ }
++ if gc.Uniqp(rr) == nil {
++ // branch target: leave alone
++ break
++ }
++ pp := rr.Prog
++ if isMove(pp) && isGPR(&pp.From) && isGPR(&pp.To) && pp.From.Reg == p.To.Reg {
++ move = rr
++ break
++ }
++ if pp.As == obj.ANOP {
++ continue
++ }
++ break
++ }
++
++ // we have a move that reads from our destination reg, check if any future
++ // instructions also read from the reg
++ if move != nil && move.Prog.From.Reg != move.Prog.To.Reg {
++ safe := false
++ visited := make(map[*gc.Flow]bool)
++ children := make([]*gc.Flow, 0)
++ if move.S1 != nil {
++ children = append(children, move.S1)
++ }
++ if move.S2 != nil {
++ children = append(children, move.S2)
++ }
++ if len(children) == 0 {
++ safe = true
++ } else {
++ for len(children) > 0 {
++ rr := children[0]
++ if visited[rr] {
++ children = children[1:]
++ continue
++ } else {
++ visited[rr] = true
++ }
++ pp := rr.Prog
++ t := copyu(pp, &p.To, nil)
++ if t == 0 { // not found
++ if rr.S1 != nil {
++ children = append(children, rr.S1)
++ }
++ if rr.S2 != nil {
++ children = append(children, rr.S2)
++ }
++ children = children[1:]
++ continue
++ }
++ if t == 3 { // set
++ children = children[1:]
++ if len(children) == 0 {
++ safe = true
++ }
++ continue
++ }
++ // t is 1, 2 or 4: use
++ break
++ }
++ }
++ if !safe {
++ move = nil
++ }
++ }
++
++ if move == nil {
++ continue
++ }
++
++ pp := move.Prog
++ execute := false
++ // at this point we have something like:
++ // MOV* anything, reg1
++ // MOV* reg1, reg2
++ // now check if this is a cast that cannot be forward propagated
++ if p.As == pp.As {
++ // if the operations match then we can always propagate
++ execute = true
++ }
++ if !execute && isGPR(&p.From) {
++ switch p.As {
++ case s390x.AMOVD:
++ fallthrough
++ case s390x.AMOVWZ:
++ if pp.As == s390x.AMOVWZ {
++ execute = true
++ break
++ }
++ fallthrough
++ case s390x.AMOVHZ:
++ if pp.As == s390x.AMOVHZ {
++ execute = true
++ break
++ }
++ fallthrough
++ case s390x.AMOVBZ:
++ if pp.As == s390x.AMOVBZ {
++ execute = true
++ break
++ }
++ }
++ }
++ if !execute {
++ if (p.As == s390x.AMOVB || p.As == s390x.AMOVBZ) && (pp.As == s390x.AMOVB || pp.As == s390x.AMOVBZ) {
++ execute = true
++ }
++ if (p.As == s390x.AMOVH || p.As == s390x.AMOVHZ) && (pp.As == s390x.AMOVH || pp.As == s390x.AMOVHZ) {
++ execute = true
++ }
++ if (p.As == s390x.AMOVW || p.As == s390x.AMOVWZ) && (pp.As == s390x.AMOVW || pp.As == s390x.AMOVWZ) {
++ execute = true
++ }
++ }
++
++ if execute {
++ pp.From = p.From
++ excise(r)
++ }
++ }
++ return
++}
++
++// fuseClear merges memory clear operations.
++//
++// Looks for this pattern (sequence of clears):
++// MOVD R0, n(R15)
++// MOVD R0, n+8(R15)
++// MOVD R0, n+16(R15)
++// Replaces with:
++// CLEAR $24, n(R15)
++func fuseClear(r *gc.Flow) {
++ var clear *obj.Prog
++ for ; r != nil; r = r.Link {
++ // If there is a branch into the instruction stream then
++ // we can't fuse into previous instructions.
++ if gc.Uniqp(r) == nil {
++ clear = nil
++ }
++
++ p := r.Prog
++ if p.As == obj.ANOP {
++ continue
++ }
++ if p.As == s390x.AXC {
++ if p.From.Reg == p.To.Reg && p.From.Offset == p.To.Offset {
++ // TODO(mundaym): merge clears?
++ p.As = s390x.ACLEAR
++ p.From.Offset = p.From3.Offset
++ p.From3 = nil
++ p.From.Type = obj.TYPE_CONST
++ p.From.Reg = 0
++ clear = p
++ } else {
++ clear = nil
++ }
++ continue
++ }
++
++ // Is our source a constant zero?
++ if regzer(&p.From) == 0 {
++ clear = nil
++ continue
++ }
++
++ // Are we moving to memory?
++ if p.To.Type != obj.TYPE_MEM ||
++ p.To.Index != 0 ||
++ p.To.Offset >= 4096 ||
++ !(p.To.Name == obj.NAME_NONE || p.To.Name == obj.NAME_AUTO || p.To.Name == obj.NAME_PARAM) {
++ clear = nil
++ continue
++ }
++
++ size := int64(0)
++ switch p.As {
++ default:
++ clear = nil
++ continue
++ case s390x.AMOVB, s390x.AMOVBZ:
++ size = 1
++ case s390x.AMOVH, s390x.AMOVHZ:
++ size = 2
++ case s390x.AMOVW, s390x.AMOVWZ:
++ size = 4
++ case s390x.AMOVD:
++ size = 8
++ }
++
++ if clear != nil &&
++ clear.To.Reg == p.To.Reg &&
++ clear.To.Name == p.To.Name &&
++ clear.To.Node == p.To.Node &&
++ clear.To.Sym == p.To.Sym {
++
++ min := clear.To.Offset
++ max := clear.To.Offset + clear.From.Offset
++
++ // previous clear is already clearing this region
++ if min <= p.To.Offset && max >= p.To.Offset+size {
++ excise(r)
++ continue
++ }
++
++ // merge forwards
++ if max == p.To.Offset {
++ clear.From.Offset += size
++ excise(r)
++ continue
++ }
++
++ // merge backwards
++ if min-size == p.To.Offset {
++ clear.From.Offset += size
++ clear.To.Offset -= size
++ excise(r)
++ continue
++ }
++ }
++
++ // transform into clear
++ p.From.Type = obj.TYPE_CONST
++ p.From.Offset = size
++ p.From.Reg = 0
++ p.As = s390x.ACLEAR
++ clear = p
++ }
++}
++
++// fuseMultiple merges memory loads and stores into load multiple and
++// store multiple operations.
++//
++// Looks for this pattern (sequence of loads or stores):
++// MOVD R1, 0(R15)
++// MOVD R2, 8(R15)
++// MOVD R3, 16(R15)
++// Replaces with:
++// STMG R1, R3, 0(R15)
++func fuseMultiple(r *gc.Flow) {
++ var fused *obj.Prog
++ for ; r != nil; r = r.Link {
++ // If there is a branch into the instruction stream then
++ // we can't fuse into previous instructions.
++ if gc.Uniqp(r) == nil {
++ fused = nil
++ }
++
++ p := r.Prog
++
++ isStore := isGPR(&p.From) && isIndirectMem(&p.To)
++ isLoad := isGPR(&p.To) && isIndirectMem(&p.From)
++
++ // are we a candidate?
++ size := int64(0)
++ switch p.As {
++ default:
++ fused = nil
++ continue
++ case obj.ANOP:
++ // skip over nops
++ continue
++ case s390x.AMOVW, s390x.AMOVWZ:
++ size = 4
++ // TODO(mundaym): 32-bit load multiple is currently not supported
++ // as it requires sign/zero extension.
++ if !isStore {
++ fused = nil
++ continue
++ }
++ case s390x.AMOVD:
++ size = 8
++ if !isLoad && !isStore {
++ fused = nil
++ continue
++ }
++ }
++
++ // If we merge two loads/stores with different source/destination Nodes
++ // then we will lose a reference the second Node which means that the
++ // compiler might mark the Node as unused and free its slot on the stack.
++ // TODO(mundaym): allow this by adding a dummy reference to the Node.
++ if fused == nil ||
++ fused.From.Node != p.From.Node ||
++ fused.From.Type != p.From.Type ||
++ fused.To.Node != p.To.Node ||
++ fused.To.Type != p.To.Type {
++ fused = p
++ continue
++ }
++
++ // check two addresses
++ ca := func(a, b *obj.Addr, offset int64) bool {
++ return a.Reg == b.Reg && a.Offset+offset == b.Offset &&
++ a.Sym == b.Sym && a.Name == b.Name
++ }
++
++ switch fused.As {
++ default:
++ fused = p
++ case s390x.AMOVW, s390x.AMOVWZ:
++ if size == 4 && fused.From.Reg+1 == p.From.Reg && ca(&fused.To, &p.To, 4) {
++ fused.As = s390x.ASTMY
++ fused.Reg = p.From.Reg
++ excise(r)
++ } else {
++ fused = p
++ }
++ case s390x.AMOVD:
++ if size == 8 && fused.From.Reg+1 == p.From.Reg && ca(&fused.To, &p.To, 8) {
++ fused.As = s390x.ASTMG
++ fused.Reg = p.From.Reg
++ excise(r)
++ } else if size == 8 && fused.To.Reg+1 == p.To.Reg && ca(&fused.From, &p.From, 8) {
++ fused.As = s390x.ALMG
++ fused.Reg = fused.To.Reg
++ fused.To.Reg = p.To.Reg
++ excise(r)
++ } else {
++ fused = p
++ }
++ case s390x.ASTMG, s390x.ASTMY:
++ if (fused.As == s390x.ASTMY && size != 4) ||
++ (fused.As == s390x.ASTMG && size != 8) {
++ fused = p
++ continue
++ }
++ offset := size * int64(fused.Reg-fused.From.Reg+1)
++ if fused.Reg+1 == p.From.Reg && ca(&fused.To, &p.To, offset) {
++ fused.Reg = p.From.Reg
++ excise(r)
++ } else {
++ fused = p
++ }
++ case s390x.ALMG:
++ offset := 8 * int64(fused.To.Reg-fused.Reg+1)
++ if size == 8 && fused.To.Reg+1 == p.To.Reg && ca(&fused.From, &p.From, offset) {
++ fused.To.Reg = p.To.Reg
++ excise(r)
++ } else {
++ fused = p
++ }
++ }
++ }
++}
diff --git a/src/cmd/compile/internal/s390x/prog.go b/src/cmd/compile/internal/s390x/prog.go
new file mode 100644
-index 0000000..591638c
+index 0000000..00cd22c
--- /dev/null
+++ b/src/cmd/compile/internal/s390x/prog.go
@@ -0,0 +1,183 @@
@@ -13411,7 +14479,7 @@ index 0000000..591638c
+ s390x.AFDIVS: {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
+ s390x.AFCMPU: {Flags: gc.SizeD | gc.LeftRead | gc.RightRead},
+ s390x.ACEBR: {Flags: gc.SizeF | gc.LeftRead | gc.RightRead},
-+ s390x.AFRSP: {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv},
++ s390x.ALEDBR: {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv},
+ s390x.ALDEBR: {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv},
+ s390x.AFSQRT: {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite},
+
@@ -13439,19 +14507,17 @@ index 0000000..591638c
+ s390x.AMOVH: {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
+ s390x.AMOVHZ: {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
+ s390x.AMOVW: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
-+
-+ // there is no AMOVWU.
+ s390x.AMOVWZ: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
+ s390x.AMOVD: {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Move},
+ s390x.AFMOVS: {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
+ s390x.AFMOVD: {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Move},
+
+ // Storage operations
-+ s390x.AMVC: {Flags: gc.SizeQ | gc.LeftRead | gc.RightRead},
-+ s390x.ACLC: {Flags: gc.SizeQ | gc.LeftRead | gc.RightRead},
-+ s390x.AXC: {Flags: gc.SizeQ | gc.LeftRead | gc.RightRead},
-+ s390x.AOC: {Flags: gc.SizeQ | gc.LeftRead | gc.RightRead},
-+ s390x.ANC: {Flags: gc.SizeQ | gc.LeftRead | gc.RightRead},
++ s390x.AMVC: {Flags: gc.LeftRead | gc.LeftAddr | gc.RightWrite | gc.RightAddr},
++ s390x.ACLC: {Flags: gc.LeftRead | gc.LeftAddr | gc.RightRead | gc.RightAddr},
++ s390x.AXC: {Flags: gc.LeftRead | gc.LeftAddr | gc.RightWrite | gc.RightAddr},
++ s390x.AOC: {Flags: gc.LeftRead | gc.LeftAddr | gc.RightWrite | gc.RightAddr},
++ s390x.ANC: {Flags: gc.LeftRead | gc.LeftAddr | gc.RightWrite | gc.RightAddr},
+
+ // Jumps
+ s390x.ABR: {Flags: gc.Jump | gc.Break},
@@ -13475,9 +14541,16 @@ index 0000000..591638c
+ s390x.ACMPUBGT: {Flags: gc.Cjmp},
+ s390x.ACMPUBLE: {Flags: gc.Cjmp},
+
-+ obj.ARET: {Flags: gc.Break},
-+ obj.ADUFFZERO: {Flags: gc.Call},
-+ obj.ADUFFCOPY: {Flags: gc.Call},
++ // Macros
++ s390x.ACLEAR: {Flags: gc.SizeQ | gc.LeftRead | gc.RightAddr | gc.RightWrite},
++
++ // Load/store multiple
++ s390x.ASTMG: {Flags: gc.SizeQ | gc.LeftRead | gc.RightAddr | gc.RightWrite},
++ s390x.ASTMY: {Flags: gc.SizeL | gc.LeftRead | gc.RightAddr | gc.RightWrite},
++ s390x.ALMG: {Flags: gc.SizeQ | gc.LeftAddr | gc.LeftRead | gc.RightWrite},
++ s390x.ALMY: {Flags: gc.SizeL | gc.LeftAddr | gc.LeftRead | gc.RightWrite},
++
++ obj.ARET: {Flags: gc.Break},
+}
+
+func proginfo(p *obj.Prog) {
@@ -13494,16 +14567,10 @@ index 0000000..591638c
+
+ if (p.From.Type == obj.TYPE_MEM || p.From.Type == obj.TYPE_ADDR) && p.From.Reg != 0 {
+ info.Regindex |= RtoB(int(p.From.Reg))
-+ if info.Flags&gc.PostInc != 0 {
-+ info.Regset |= RtoB(int(p.From.Reg))
-+ }
+ }
+
+ if (p.To.Type == obj.TYPE_MEM || p.To.Type == obj.TYPE_ADDR) && p.To.Reg != 0 {
+ info.Regindex |= RtoB(int(p.To.Reg))
-+ if info.Flags&gc.PostInc != 0 {
-+ info.Regset |= RtoB(int(p.To.Reg))
-+ }
+ }
+
+ if p.From.Type == obj.TYPE_ADDR && p.From.Sym != nil && (info.Flags&gc.LeftRead != 0) {
@@ -13511,16 +14578,17 @@ index 0000000..591638c
+ info.Flags |= gc.LeftAddr
+ }
+
-+ if p.As == obj.ADUFFZERO {
-+ info.Reguse |= 1<<0 | RtoB(s390x.REG_R3)
-+ info.Regset |= RtoB(s390x.REG_R3)
-+ }
-+
-+ if p.As == obj.ADUFFCOPY {
-+ // TODO(austin) Revisit when duffcopy is implemented
-+ info.Reguse |= RtoB(s390x.REG_R3) | RtoB(s390x.REG_R4) | RtoB(s390x.REG_R5)
-+
-+ info.Regset |= RtoB(s390x.REG_R3) | RtoB(s390x.REG_R4)
++ switch p.As {
++ // load multiple sets a range of registers
++ case s390x.ALMG, s390x.ALMY:
++ for r := p.Reg; r <= p.To.Reg; r++ {
++ info.Regset |= RtoB(int(r))
++ }
++ // store multiple reads a range of registers
++ case s390x.ASTMG, s390x.ASTMY:
++ for r := p.From.Reg; r <= p.Reg; r++ {
++ info.Reguse |= RtoB(int(r))
++ }
+ }
+}
diff --git a/src/cmd/compile/internal/s390x/reg.go b/src/cmd/compile/internal/s390x/reg.go
@@ -13681,7 +14749,7 @@ index 3d11f51..66bbf84 100644
}
}
diff --git a/src/cmd/dist/build.go b/src/cmd/dist/build.go
-index 39a88cc..e8b5862 100644
+index 39a88cc..3cb3028 100644
--- a/src/cmd/dist/build.go
+++ b/src/cmd/dist/build.go
@@ -58,6 +58,7 @@ var okgoarch = []string{
@@ -13692,6 +14760,48 @@ index 39a88cc..e8b5862 100644
}
// The known operating systems.
+@@ -754,7 +755,7 @@ func matchtag(tag string) bool {
+ }
+ return !matchtag(tag[1:])
+ }
+- return tag == goos || tag == goarch || tag == "cmd_go_bootstrap" || tag == "go1.1" || (goos == "android" && tag == "linux")
++ return tag == "gc" || tag == goos || tag == goarch || tag == "cmd_go_bootstrap" || tag == "go1.1" || (goos == "android" && tag == "linux")
+ }
+
+ // shouldbuild reports whether we should build this file.
+@@ -798,10 +799,15 @@ func shouldbuild(file, dir string) bool {
+ if p == "" {
+ continue
+ }
+- if strings.Contains(p, "package documentation") {
++ code := p
++ i := strings.Index(code, "//")
++ if i > 0 {
++ code = strings.TrimSpace(code[:i])
++ }
++ if code == "package documentation" {
+ return false
+ }
+- if strings.Contains(p, "package main") && dir != "cmd/go" && dir != "cmd/cgo" {
++ if code == "package main" && dir != "cmd/go" && dir != "cmd/cgo" {
+ return false
+ }
+ if !strings.HasPrefix(p, "//") {
+@@ -810,11 +816,11 @@ func shouldbuild(file, dir string) bool {
+ if !strings.Contains(p, "+build") {
+ continue
+ }
+- fields := splitfields(p)
+- if len(fields) < 2 || fields[1] != "+build" {
++ fields := splitfields(p[2:])
++ if len(fields) < 1 || fields[0] != "+build" {
+ continue
+ }
+- for _, p := range fields[2:] {
++ for _, p := range fields[1:] {
+ if matchfield(p) {
+ goto fieldmatch
+ }
diff --git a/src/cmd/dist/buildtool.go b/src/cmd/dist/buildtool.go
index 20d9535..c8ab50e 100644
--- a/src/cmd/dist/buildtool.go
@@ -13721,7 +14831,7 @@ index 20d9535..c8ab50e 100644
func bootstrapBuildTools() {
diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go
-index 156b868..ef23b34 100644
+index 36c829d..320f10d 100644
--- a/src/cmd/dist/test.go
+++ b/src/cmd/dist/test.go
@@ -667,7 +667,7 @@ func (t *tester) supportedBuildmode(mode string) bool {
@@ -13755,8 +14865,34 @@ index 1b5d1f9..cf8966d 100644
case gohostos == "darwin":
if strings.Contains(run("", CheckExit, "uname", "-v"), "RELEASE_ARM_") {
gohostarch = "arm"
+diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go
+index c81bd40..bbad8d4 100644
+--- a/src/cmd/go/alldocs.go
++++ b/src/cmd/go/alldocs.go
+@@ -1022,12 +1022,6 @@ Vendor directories do not affect the placement of new repositories
+ being checked out for the first time by 'go get': those are always
+ placed in the main GOPATH, never in a vendor subtree.
+
+-In Go 1.5, as an experiment, setting the environment variable
+-GO15VENDOREXPERIMENT=1 enabled these features.
+-As of Go 1.6 they are on by default. To turn them off, set
+-GO15VENDOREXPERIMENT=0. In Go 1.7, the environment
+-variable will stop having any effect.
+-
+ See https://golang.org/s/go15vendor for details.
+
+
+@@ -1094,8 +1088,6 @@ Special-purpose environment variables:
+ installed in a location other than where it is built.
+ File names in stack traces are rewritten from GOROOT to
+ GOROOT_FINAL.
+- GO15VENDOREXPERIMENT
+- Set to 0 to disable vendoring semantics.
+ GO_EXTLINK_ENABLED
+ Whether the linker should use external linking mode
+ when using -linkmode=auto with code that uses cgo.
diff --git a/src/cmd/go/build.go b/src/cmd/go/build.go
-index a1f925e..fffb40c 100644
+index f2a2a60..af5f2d3 100644
--- a/src/cmd/go/build.go
+++ b/src/cmd/go/build.go
@@ -377,7 +377,7 @@ func buildModeInit() {
@@ -13786,7 +14922,80 @@ index a1f925e..fffb40c 100644
buildAsmflags = append(buildAsmflags, "-D=GOBUILDMODE_shared=1")
default:
fatalf("-linkshared not supported on %s\n", platform)
-@@ -2958,6 +2958,8 @@ func (b *builder) gccArchArgs() []string {
+@@ -686,6 +686,7 @@ type builder struct {
+ work string // the temporary work directory (ends in filepath.Separator)
+ actionCache map[cacheKey]*action // a cache of already-constructed actions
+ mkdirCache map[string]bool // a cache of created directories
++ flagCache map[string]bool // a cache of supported compiler flags
+ print func(args ...interface{}) (int, error)
+
+ output sync.Mutex
+@@ -2927,6 +2928,17 @@ func (b *builder) ccompilerCmd(envvar, defcmd, objdir string) []string {
+ // disable word wrapping in error messages
+ a = append(a, "-fmessage-length=0")
+
++ // Tell gcc not to include the work directory in object files.
++ if b.gccSupportsFlag("-fdebug-prefix-map=a=b") {
++ a = append(a, "-fdebug-prefix-map="+b.work+"=/tmp/go-build")
++ }
++
++ // Tell gcc not to include flags in object files, which defeats the
++ // point of -fdebug-prefix-map above.
++ if b.gccSupportsFlag("-gno-record-gcc-switches") {
++ a = append(a, "-gno-record-gcc-switches")
++ }
++
+ // On OS X, some of the compilers behave as if -fno-common
+ // is always set, and the Mach-O linker in 6l/8l assumes this.
+ // See https://golang.org/issue/3253.
+@@ -2941,19 +2953,24 @@ func (b *builder) ccompilerCmd(envvar, defcmd, objdir string) []string {
+ // -no-pie must be passed when doing a partial link with -Wl,-r. But -no-pie is
+ // not supported by all compilers.
+ func (b *builder) gccSupportsNoPie() bool {
+- if goos != "linux" {
+- // On some BSD platforms, error messages from the
+- // compiler make it to the console despite cmd.Std*
+- // all being nil. As -no-pie is only required on linux
+- // systems so far, we only test there.
+- return false
++ return b.gccSupportsFlag("-no-pie")
++}
++
++// gccSupportsFlag checks to see if the compiler supports a flag.
++func (b *builder) gccSupportsFlag(flag string) bool {
++ b.exec.Lock()
++ defer b.exec.Unlock()
++ if b, ok := b.flagCache[flag]; ok {
++ return b
+ }
+- src := filepath.Join(b.work, "trivial.c")
+- if err := ioutil.WriteFile(src, []byte{}, 0666); err != nil {
+- return false
++ if b.flagCache == nil {
++ src := filepath.Join(b.work, "trivial.c")
++ if err := ioutil.WriteFile(src, []byte{}, 0666); err != nil {
++ return false
++ }
++ b.flagCache = make(map[string]bool)
+ }
+- cmdArgs := b.gccCmd(b.work)
+- cmdArgs = append(cmdArgs, "-no-pie", "-c", "trivial.c")
++ cmdArgs := append(envList("CC", defaultCC), flag, "-c", "trivial.c")
+ if buildN || buildX {
+ b.showcmd(b.work, "%s", joinUnambiguously(cmdArgs))
+ if buildN {
+@@ -2964,7 +2981,9 @@ func (b *builder) gccSupportsNoPie() bool {
+ cmd.Dir = b.work
+ cmd.Env = envForDir(cmd.Dir, os.Environ())
+ out, err := cmd.CombinedOutput()
+- return err == nil && !bytes.Contains(out, []byte("unrecognized"))
++ supported := err == nil && !bytes.Contains(out, []byte("unrecognized"))
++ b.flagCache[flag] = supported
++ return supported
+ }
+
+ // gccArchArgs returns arguments to pass to gcc based on the architecture.
+@@ -2976,6 +2995,8 @@ func (b *builder) gccArchArgs() []string {
return []string{"-m64"}
case "arm":
return []string{"-marm"} // not thumb
@@ -13795,26 +15004,397 @@ index a1f925e..fffb40c 100644
}
return nil
}
-diff --git a/src/cmd/internal/obj/link.go b/src/cmd/internal/obj/link.go
-index 762a49e..465e4d0 100644
---- a/src/cmd/internal/obj/link.go
-+++ b/src/cmd/internal/obj/link.go
-@@ -521,6 +521,9 @@ const (
- // R_ADDRPOWER_DS but inserts the offset from the TOC to the address of the the
- // relocated symbol rather than the symbol's address.
- R_ADDRPOWER_TOCREL_DS
+diff --git a/src/cmd/go/env.go b/src/cmd/go/env.go
+index 24f6127..8d427b3 100644
+--- a/src/cmd/go/env.go
++++ b/src/cmd/go/env.go
+@@ -33,11 +33,6 @@ func mkEnv() []envVar {
+ var b builder
+ b.init()
+
+- vendorExpValue := "0"
+- if go15VendorExperiment {
+- vendorExpValue = "1"
+- }
+-
+ env := []envVar{
+ {"GOARCH", goarch},
+ {"GOBIN", gobin},
+@@ -49,7 +44,6 @@ func mkEnv() []envVar {
+ {"GORACE", os.Getenv("GORACE")},
+ {"GOROOT", goroot},
+ {"GOTOOLDIR", toolDir},
+- {"GO15VENDOREXPERIMENT", vendorExpValue},
+
+ // disable escape codes in clang errors
+ {"TERM", "dumb"},
+diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go
+index 39e0f3e..ae42608 100644
+--- a/src/cmd/go/go_test.go
++++ b/src/cmd/go/go_test.go
+@@ -1657,8 +1657,8 @@ func TestLdflagsArgumentsWithSpacesIssue3941(t *testing.T) {
+ func main() {
+ println(extern)
+ }`)
+- tg.run("run", "-ldflags", `-X main.extern "hello world"`, tg.path("main.go"))
+- tg.grepStderr("^hello world", `ldflags -X main.extern 'hello world' failed`)
++ tg.run("run", "-ldflags", `-X "main.extern=hello world"`, tg.path("main.go"))
++ tg.grepStderr("^hello world", `ldflags -X "main.extern=hello world"' failed`)
+ }
+
+ func TestGoTestCpuprofileLeavesBinaryBehind(t *testing.T) {
+@@ -1726,7 +1726,6 @@ func TestSymlinksVendor(t *testing.T) {
+
+ tg := testgo(t)
+ defer tg.cleanup()
+- tg.setenv("GO15VENDOREXPERIMENT", "1")
+ tg.tempDir("gopath/src/dir1/vendor/v")
+ tg.tempFile("gopath/src/dir1/p.go", "package main\nimport _ `v`\nfunc main(){}")
+ tg.tempFile("gopath/src/dir1/vendor/v/v.go", "package v")
+@@ -2759,3 +2758,30 @@ func TestParallelTest(t *testing.T) {
+ tg.setenv("GOPATH", tg.path("."))
+ tg.run("test", "-p=4", "p1", "p2", "p3", "p4")
+ }
+
-+ // R_PCRELDBL is for S390x (z) 2-byte aligned addresses (e.g. R_390_PLT32DBL)
-+ R_PCRELDBL
- )
++func TestCgoConsistentResults(t *testing.T) {
++ if !canCgo {
++ t.Skip("skipping because cgo not enabled")
++ }
++
++ tg := testgo(t)
++ defer tg.cleanup()
++ tg.parallel()
++ tg.makeTempdir()
++ tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
++ exe1 := tg.path("cgotest1" + exeSuffix)
++ exe2 := tg.path("cgotest2" + exeSuffix)
++ tg.run("build", "-o", exe1, "cgotest")
++ tg.run("build", "-x", "-o", exe2, "cgotest")
++ b1, err := ioutil.ReadFile(exe1)
++ tg.must(err)
++ b2, err := ioutil.ReadFile(exe2)
++ tg.must(err)
++
++ if !tg.doGrepMatch(`-fdebug-prefix-map=\$WORK`, &tg.stderr) {
++ t.Skip("skipping because C compiler does not support -fdebug-prefix-map")
++ }
++ if !bytes.Equal(b1, b2) {
++ t.Error("building cgotest twice did not produce the same output")
++ }
++}
+diff --git a/src/cmd/go/help.go b/src/cmd/go/help.go
+index d8e7efe..de5e5dd 100644
+--- a/src/cmd/go/help.go
++++ b/src/cmd/go/help.go
+@@ -421,12 +421,6 @@ Vendor directories do not affect the placement of new repositories
+ being checked out for the first time by 'go get': those are always
+ placed in the main GOPATH, never in a vendor subtree.
- type Auto struct {
-diff --git a/src/cmd/internal/obj/s390x/a.out.go b/src/cmd/internal/obj/s390x/a.out.go
-new file mode 100644
-index 0000000..a809306
---- /dev/null
-+++ b/src/cmd/internal/obj/s390x/a.out.go
-@@ -0,0 +1,360 @@
+-In Go 1.5, as an experiment, setting the environment variable
+-GO15VENDOREXPERIMENT=1 enabled these features.
+-As of Go 1.6 they are on by default. To turn them off, set
+-GO15VENDOREXPERIMENT=0. In Go 1.7, the environment
+-variable will stop having any effect.
+-
+ See https://golang.org/s/go15vendor for details.
+ `,
+ }
+@@ -497,8 +491,6 @@ Special-purpose environment variables:
+ installed in a location other than where it is built.
+ File names in stack traces are rewritten from GOROOT to
+ GOROOT_FINAL.
+- GO15VENDOREXPERIMENT
+- Set to 0 to disable vendoring semantics.
+ GO_EXTLINK_ENABLED
+ Whether the linker should use external linking mode
+ when using -linkmode=auto with code that uses cgo.
+diff --git a/src/cmd/go/pkg.go b/src/cmd/go/pkg.go
+index 0c0cf07..6b5ead2 100644
+--- a/src/cmd/go/pkg.go
++++ b/src/cmd/go/pkg.go
+@@ -263,15 +263,6 @@ func reloadPackage(arg string, stk *importStack) *Package {
+ return loadPackage(arg, stk)
+ }
+
+-// The Go 1.5 vendoring experiment was enabled by setting GO15VENDOREXPERIMENT=1.
+-// In Go 1.6 this is on by default and is disabled by setting GO15VENDOREXPERIMENT=0.
+-// In Go 1.7 the variable will stop having any effect.
+-// The variable is obnoxiously long so that years from now when people find it in
+-// their profiles and wonder what it does, there is some chance that a web search
+-// might answer the question.
+-// There is a copy of this variable in src/go/build/build.go. Delete that one when this one goes away.
+-var go15VendorExperiment = os.Getenv("GO15VENDOREXPERIMENT") != "0"
+-
+ // dirToImportPath returns the pseudo-import path we use for a package
+ // outside the Go path. It begins with _/ and then contains the full path
+ // to the directory. If the package lives in c:\home\gopher\my\pkg then
+@@ -361,7 +352,7 @@ func loadImport(path, srcDir string, parent *Package, stk *importStack, importPo
+ // TODO: After Go 1, decide when to pass build.AllowBinary here.
+ // See issue 3268 for mistakes to avoid.
+ buildMode := build.ImportComment
+- if !go15VendorExperiment || mode&useVendor == 0 || path != origPath {
++ if mode&useVendor == 0 || path != origPath {
+ // Not vendoring, or we already found the vendored path.
+ buildMode |= build.IgnoreVendor
+ }
+@@ -371,7 +362,7 @@ func loadImport(path, srcDir string, parent *Package, stk *importStack, importPo
+ bp.BinDir = gobin
+ }
+ if err == nil && !isLocal && bp.ImportComment != "" && bp.ImportComment != path &&
+- (!go15VendorExperiment || (!strings.Contains(path, "/vendor/") && !strings.HasPrefix(path, "vendor/"))) {
++ !strings.Contains(path, "/vendor/") && !strings.HasPrefix(path, "vendor/") {
+ err = fmt.Errorf("code in directory %s expects import %q", bp.Dir, bp.ImportComment)
+ }
+ p.load(stk, bp, err)
+@@ -412,7 +403,7 @@ func isDir(path string) bool {
+ // x/vendor/path, vendor/path, or else stay path if none of those exist.
+ // vendoredImportPath returns the expanded path or, if no expansion is found, the original.
+ func vendoredImportPath(parent *Package, path string) (found string) {
+- if parent == nil || parent.Root == "" || !go15VendorExperiment {
++ if parent == nil || parent.Root == "" {
+ return path
+ }
+
+@@ -580,10 +571,6 @@ func findInternal(path string) (index int, ok bool) {
+ // If the import is allowed, disallowVendor returns the original package p.
+ // If not, it returns a new package containing just an appropriate error.
+ func disallowVendor(srcDir, path string, p *Package, stk *importStack) *Package {
+- if !go15VendorExperiment {
+- return p
+- }
+-
+ // The stack includes p.ImportPath.
+ // If that's the only thing on the stack, we started
+ // with a name given on the command line, not an
+diff --git a/src/cmd/go/vcs.go b/src/cmd/go/vcs.go
+index 342edee..797d91f 100644
+--- a/src/cmd/go/vcs.go
++++ b/src/cmd/go/vcs.go
+@@ -383,7 +383,7 @@ func (v *vcsCmd) ping(scheme, repo string) error {
+ // The parent of dir must exist; dir must not.
+ func (v *vcsCmd) create(dir, repo string) error {
+ for _, cmd := range v.createCmd {
+- if !go15VendorExperiment && strings.Contains(cmd, "submodule") {
++ if strings.Contains(cmd, "submodule") {
+ continue
+ }
+ if err := v.run(".", cmd, "dir", dir, "repo", repo); err != nil {
+@@ -396,7 +396,7 @@ func (v *vcsCmd) create(dir, repo string) error {
+ // download downloads any new changes for the repo in dir.
+ func (v *vcsCmd) download(dir string) error {
+ for _, cmd := range v.downloadCmd {
+- if !go15VendorExperiment && strings.Contains(cmd, "submodule") {
++ if strings.Contains(cmd, "submodule") {
+ continue
+ }
+ if err := v.run(dir, cmd); err != nil {
+@@ -445,7 +445,7 @@ func (v *vcsCmd) tagSync(dir, tag string) error {
+
+ if tag == "" && v.tagSyncDefault != nil {
+ for _, cmd := range v.tagSyncDefault {
+- if !go15VendorExperiment && strings.Contains(cmd, "submodule") {
++ if strings.Contains(cmd, "submodule") {
+ continue
+ }
+ if err := v.run(dir, cmd); err != nil {
+@@ -456,7 +456,7 @@ func (v *vcsCmd) tagSync(dir, tag string) error {
+ }
+
+ for _, cmd := range v.tagSyncCmd {
+- if !go15VendorExperiment && strings.Contains(cmd, "submodule") {
++ if strings.Contains(cmd, "submodule") {
+ continue
+ }
+ if err := v.run(dir, cmd, "tag", tag); err != nil {
+diff --git a/src/cmd/go/vendor_test.go b/src/cmd/go/vendor_test.go
+index 006a8c9..40fe309 100644
+--- a/src/cmd/go/vendor_test.go
++++ b/src/cmd/go/vendor_test.go
+@@ -20,7 +20,6 @@ func TestVendorImports(t *testing.T) {
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
+- tg.setenv("GO15VENDOREXPERIMENT", "1")
+ tg.run("list", "-f", "{{.ImportPath}} {{.Imports}}", "vend/...")
+ want := `
+ vend [vend/vendor/p r]
+@@ -51,7 +50,6 @@ func TestVendorBuild(t *testing.T) {
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
+- tg.setenv("GO15VENDOREXPERIMENT", "1")
+ tg.run("build", "vend/x")
+ }
+
+@@ -59,7 +57,6 @@ func TestVendorRun(t *testing.T) {
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
+- tg.setenv("GO15VENDOREXPERIMENT", "1")
+ tg.cd(filepath.Join(tg.pwd(), "testdata/src/vend/hello"))
+ tg.run("run", "hello.go")
+ tg.grepStdout("hello, world", "missing hello world output")
+@@ -74,7 +71,6 @@ func TestVendorGOPATH(t *testing.T) {
+ }
+ gopath := changeVolume(filepath.Join(tg.pwd(), "testdata"), strings.ToLower)
+ tg.setenv("GOPATH", gopath)
+- tg.setenv("GO15VENDOREXPERIMENT", "1")
+ cd := changeVolume(filepath.Join(tg.pwd(), "testdata/src/vend/hello"), strings.ToUpper)
+ tg.cd(cd)
+ tg.run("run", "hello.go")
+@@ -85,7 +81,6 @@ func TestVendorTest(t *testing.T) {
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
+- tg.setenv("GO15VENDOREXPERIMENT", "1")
+ tg.cd(filepath.Join(tg.pwd(), "testdata/src/vend/hello"))
+ tg.run("test", "-v")
+ tg.grepStdout("TestMsgInternal", "missing use in internal test")
+@@ -96,7 +91,6 @@ func TestVendorInvalid(t *testing.T) {
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
+- tg.setenv("GO15VENDOREXPERIMENT", "1")
+
+ tg.runFail("build", "vend/x/invalid")
+ tg.grepStderr("must be imported as foo", "missing vendor import error")
+@@ -106,7 +100,6 @@ func TestVendorImportError(t *testing.T) {
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
+- tg.setenv("GO15VENDOREXPERIMENT", "1")
+
+ tg.runFail("build", "vend/x/vendor/p/p")
+
+@@ -173,7 +166,6 @@ func TestVendorGet(t *testing.T) {
+ package p
+ const C = 1`)
+ tg.setenv("GOPATH", tg.path("."))
+- tg.setenv("GO15VENDOREXPERIMENT", "1")
+ tg.cd(tg.path("src/v"))
+ tg.run("run", "m.go")
+ tg.run("test")
+@@ -192,7 +184,6 @@ func TestVendorGetUpdate(t *testing.T) {
+ defer tg.cleanup()
+ tg.makeTempdir()
+ tg.setenv("GOPATH", tg.path("."))
+- tg.setenv("GO15VENDOREXPERIMENT", "1")
+ tg.run("get", "github.com/rsc/go-get-issue-11864")
+ tg.run("get", "-u", "github.com/rsc/go-get-issue-11864")
+ }
+@@ -204,7 +195,6 @@ func TestGetSubmodules(t *testing.T) {
+ defer tg.cleanup()
+ tg.makeTempdir()
+ tg.setenv("GOPATH", tg.path("."))
+- tg.setenv("GO15VENDOREXPERIMENT", "1")
+ tg.run("get", "-d", "github.com/rsc/go-get-issue-12612")
+ tg.run("get", "-u", "-d", "github.com/rsc/go-get-issue-12612")
+ }
+@@ -213,7 +203,6 @@ func TestVendorCache(t *testing.T) {
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata/testvendor"))
+- tg.setenv("GO15VENDOREXPERIMENT", "1")
+ tg.runFail("build", "p")
+ tg.grepStderr("must be imported as x", "did not fail to build p")
+ }
+@@ -225,7 +214,6 @@ func TestVendorTest2(t *testing.T) {
+ defer tg.cleanup()
+ tg.makeTempdir()
+ tg.setenv("GOPATH", tg.path("."))
+- tg.setenv("GO15VENDOREXPERIMENT", "1")
+ tg.run("get", "github.com/rsc/go-get-issue-11864")
+
+ // build -i should work
+@@ -251,7 +239,6 @@ func TestVendorList(t *testing.T) {
+ defer tg.cleanup()
+ tg.makeTempdir()
+ tg.setenv("GOPATH", tg.path("."))
+- tg.setenv("GO15VENDOREXPERIMENT", "1")
+ tg.run("get", "github.com/rsc/go-get-issue-11864")
+
+ tg.run("list", "-f", `{{join .TestImports "\n"}}`, "github.com/rsc/go-get-issue-11864/t")
+@@ -272,7 +259,6 @@ func TestVendor12156(t *testing.T) {
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata/testvendor2"))
+- tg.setenv("GO15VENDOREXPERIMENT", "1")
+ tg.cd(filepath.Join(tg.pwd(), "testdata/testvendor2/src/p"))
+ tg.runFail("build", "p.go")
+ tg.grepStderrNot("panic", "panicked")
+diff --git a/src/cmd/gofmt/gofmt.go b/src/cmd/gofmt/gofmt.go
+index cfebeff..b10b804 100644
+--- a/src/cmd/gofmt/gofmt.go
++++ b/src/cmd/gofmt/gofmt.go
+@@ -143,7 +143,9 @@ func visitFile(path string, f os.FileInfo, err error) error {
+ if err == nil && isGoFile(f) {
+ err = processFile(path, nil, os.Stdout, false)
+ }
+- if err != nil {
++ // Don't complain if a file was deleted in the meantime (i.e.
++ // the directory changed concurrently while running gofmt).
++ if err != nil && !os.IsNotExist(err) {
+ report(err)
+ }
+ return nil
+diff --git a/src/cmd/internal/obj/link.go b/src/cmd/internal/obj/link.go
+index 762a49e..465e4d0 100644
+--- a/src/cmd/internal/obj/link.go
++++ b/src/cmd/internal/obj/link.go
+@@ -521,6 +521,9 @@ const (
+ // R_ADDRPOWER_DS but inserts the offset from the TOC to the address of the the
+ // relocated symbol rather than the symbol's address.
+ R_ADDRPOWER_TOCREL_DS
++
++ // R_PCRELDBL is for S390x (z) 2-byte aligned addresses (e.g. R_390_PLT32DBL)
++ R_PCRELDBL
+ )
+
+ type Auto struct {
+diff --git a/src/cmd/internal/obj/obj.go b/src/cmd/internal/obj/obj.go
+index 30ab549..343c93a 100644
+--- a/src/cmd/internal/obj/obj.go
++++ b/src/cmd/internal/obj/obj.go
+@@ -281,3 +281,21 @@ func linkgetline(ctxt *Link, lineno int32, f **LSym, l *int32) {
+ func Linkprfile(ctxt *Link, line int) {
+ fmt.Printf("%s ", ctxt.LineHist.LineString(line))
+ }
++
++func fieldtrack(ctxt *Link, cursym *LSym) {
++ p := cursym.Text
++ if p == nil || p.Link == nil { // handle external functions and ELF section symbols
++ return
++ }
++ ctxt.Cursym = cursym
++
++ for ; p != nil; p = p.Link {
++ if p.As == AUSEFIELD {
++ r := Addrel(ctxt.Cursym)
++ r.Off = 0
++ r.Siz = 0
++ r.Sym = p.From.Sym
++ r.Type = R_USEFIELD
++ }
++ }
++}
+diff --git a/src/cmd/internal/obj/objfile.go b/src/cmd/internal/obj/objfile.go
+index 8d4a506..bae64f4 100644
+--- a/src/cmd/internal/obj/objfile.go
++++ b/src/cmd/internal/obj/objfile.go
+@@ -298,6 +298,7 @@ func Flushplist(ctxt *Link) {
+ ctxt.Arch.Follow(ctxt, s)
+ ctxt.Arch.Preprocess(ctxt, s)
+ ctxt.Arch.Assemble(ctxt, s)
++ fieldtrack(ctxt, s)
+ linkpcln(ctxt, s)
+ }
+
+diff --git a/src/cmd/internal/obj/s390x/a.out.go b/src/cmd/internal/obj/s390x/a.out.go
+new file mode 100644
+index 0000000..72fd427
+--- /dev/null
++++ b/src/cmd/internal/obj/s390x/a.out.go
+@@ -0,0 +1,908 @@
+// Based on cmd/internal/obj/ppc64/a.out.go.
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
@@ -13895,6 +15475,43 @@ index 0000000..a809306
+ REG_F14
+ REG_F15
+
++ // V0-V15 are aliases for F0-F15
++ // We keep them in a separate space to make printing etc. easier
++ // If the code generator ever emits vector instructions it will
++ // need to take into account the aliasing.
++ REG_V0
++ REG_V1
++ REG_V2
++ REG_V3
++ REG_V4
++ REG_V5
++ REG_V6
++ REG_V7
++ REG_V8
++ REG_V9
++ REG_V10
++ REG_V11
++ REG_V12
++ REG_V13
++ REG_V14
++ REG_V15
++ REG_V16
++ REG_V17
++ REG_V18
++ REG_V19
++ REG_V20
++ REG_V21
++ REG_V22
++ REG_V23
++ REG_V24
++ REG_V25
++ REG_V26
++ REG_V27
++ REG_V28
++ REG_V29
++ REG_V30
++ REG_V31
++
+ REG_AR0
+ REG_AR1
+ REG_AR2
@@ -13958,37 +15575,36 @@ index 0000000..a809306
+)
+
+const ( // comments from func aclass in asmz.go
-+ C_NONE = iota
-+ C_REG // general-purpose register
-+ C_FREG // floating-point register
-+ C_AREG // access register
-+ C_ZCON // constant == 0
-+ C_SCON // 0 <= constant <= 0x7fff (positive int16)
-+ C_UCON // constant & 0xffff == 0 (int32 or uint32)
-+ C_ADDCON // 0 > constant >= -0x8000 (negative int16)
-+ C_ANDCON // constant <= 0xffff
-+ C_LCON // constant (int32 or uint32)
-+ C_DCON // constant (int64 or uint64)
-+ C_SACON // computed address, 16-bit displacement, possibly SP-relative
-+ C_SECON // computed address, 16-bit displacement, possibly SB-relative, unused?
-+ C_LACON // computed address, 32-bit displacement, possibly SP-relative
-+ C_LECON // computed address, 32-bit displacement, possibly SB-relative, unused?
-+ C_DACON // computed address, 64-bit displacment?
-+ C_SBRA // short branch
-+ C_LBRA // long branch
-+ C_SAUTO // short auto
-+ C_LAUTO // long auto
-+ C_ZOREG // heap address, register-based, displacement == 0
-+ C_SOREG // heap address, register-based, int16 displacement
-+ C_LOREG // heap address, register-based, int32 displacement
-+ C_TLS_LE // TLS - local exec model (for executables)
-+ C_TLS_IE // TLS - initial exec model (for shared libraries loaded at program startup)
-+ C_ANY
++ C_NONE = iota
++ C_REG // general-purpose register (64-bit)
++ C_FREG // floating-point register (64-bit)
++ C_VREG // vector register (128-bit)
++ C_AREG // access register (32-bit)
++ C_ZCON // constant == 0
++ C_SCON // 0 <= constant <= 0x7fff (positive int16)
++ C_UCON // constant & 0xffff == 0 (int16 or uint16)
++ C_ADDCON // 0 > constant >= -0x8000 (negative int16)
++ C_ANDCON // constant <= 0xffff
++ C_LCON // constant (int32 or uint32)
++ C_DCON // constant (int64 or uint64)
++ C_SACON // computed address, 16-bit displacement, possibly SP-relative
++ C_LACON // computed address, 32-bit displacement, possibly SP-relative
++ C_DACON // computed address, 64-bit displacment?
++ C_SBRA // short branch
++ C_LBRA // long branch
++ C_SAUTO // short auto
++ C_LAUTO // long auto
++ C_ZOREG // heap address, register-based, displacement == 0
++ C_SOREG // heap address, register-based, int16 displacement
++ C_LOREG // heap address, register-based, int32 displacement
++ C_TLS_LE // TLS - local exec model (for executables)
++ C_TLS_IE // TLS - initial exec model (for shared libraries loaded at program startup)
+ C_GOK // general address
+ C_ADDR // relocation for extern or static symbols
+ C_GOTADDR // GOT slot for a symbol in -dynlink mode
+ C_TEXTSIZE // text size
-+ C_NCLASS // must be the last
++ C_ANY
++ C_NCLASS // must be the last
+)
+
+const (
@@ -14073,7 +15689,7 @@ index 0000000..a809306
+ AFNMADDS
+ AFNMSUB
+ AFNMSUBS
-+ AFRSP
++ ALEDBR
+ ALDEBR
+ AFSUB
+ AFSUBS
@@ -14157,12 +15773,524 @@ index 0000000..a809306
+ ALA
+ ALAY
+
++ // load/store multiple
++ ALMY
++ ALMG
++ ASTMY
++ ASTMG
++
+ // store clock
+ ASTCK
+ ASTCKC
+ ASTCKE
+ ASTCKF
+
++ // macros
++ ACLEAR
++
++ // vector
++ AVA
++ AVAB
++ AVAH
++ AVAF
++ AVAG
++ AVAQ
++ AVACC
++ AVACCB
++ AVACCH
++ AVACCF
++ AVACCG
++ AVACCQ
++ AVAC
++ AVACQ
++ AVACCC
++ AVACCCQ
++ AVN
++ AVNC
++ AVAVG
++ AVAVGB
++ AVAVGH
++ AVAVGF
++ AVAVGG
++ AVAVGL
++ AVAVGLB
++ AVAVGLH
++ AVAVGLF
++ AVAVGLG
++ AVCKSM
++ AVCEQ
++ AVCEQB
++ AVCEQH
++ AVCEQF
++ AVCEQG
++ AVCEQBS
++ AVCEQHS
++ AVCEQFS
++ AVCEQGS
++ AVCH
++ AVCHB
++ AVCHH
++ AVCHF
++ AVCHG
++ AVCHBS
++ AVCHHS
++ AVCHFS
++ AVCHGS
++ AVCHL
++ AVCHLB
++ AVCHLH
++ AVCHLF
++ AVCHLG
++ AVCHLBS
++ AVCHLHS
++ AVCHLFS
++ AVCHLGS
++ AVCLZ
++ AVCLZB
++ AVCLZH
++ AVCLZF
++ AVCLZG
++ AVCTZ
++ AVCTZB
++ AVCTZH
++ AVCTZF
++ AVCTZG
++ AVEC
++ AVECB
++ AVECH
++ AVECF
++ AVECG
++ AVECL
++ AVECLB
++ AVECLH
++ AVECLF
++ AVECLG
++ AVERIM
++ AVERIMB
++ AVERIMH
++ AVERIMF
++ AVERIMG
++ AVERLL
++ AVERLLB
++ AVERLLH
++ AVERLLF
++ AVERLLG
++ AVERLLV
++ AVERLLVB
++ AVERLLVH
++ AVERLLVF
++ AVERLLVG
++ AVESLV
++ AVESLVB
++ AVESLVH
++ AVESLVF
++ AVESLVG
++ AVESL
++ AVESLB
++ AVESLH
++ AVESLF
++ AVESLG
++ AVESRA
++ AVESRAB
++ AVESRAH
++ AVESRAF
++ AVESRAG
++ AVESRAV
++ AVESRAVB
++ AVESRAVH
++ AVESRAVF
++ AVESRAVG
++ AVESRL
++ AVESRLB
++ AVESRLH
++ AVESRLF
++ AVESRLG
++ AVESRLV
++ AVESRLVB
++ AVESRLVH
++ AVESRLVF
++ AVESRLVG
++ AVX
++ AVFAE
++ AVFAEB
++ AVFAEH
++ AVFAEF
++ AVFAEBS
++ AVFAEHS
++ AVFAEFS
++ AVFAEZB
++ AVFAEZH
++ AVFAEZF
++ AVFAEZBS
++ AVFAEZHS
++ AVFAEZFS
++ AVFEE
++ AVFEEB
++ AVFEEH
++ AVFEEF
++ AVFEEBS
++ AVFEEHS
++ AVFEEFS
++ AVFEEZB
++ AVFEEZH
++ AVFEEZF
++ AVFEEZBS
++ AVFEEZHS
++ AVFEEZFS
++ AVFENE
++ AVFENEB
++ AVFENEH
++ AVFENEF
++ AVFENEBS
++ AVFENEHS
++ AVFENEFS
++ AVFENEZB
++ AVFENEZH
++ AVFENEZF
++ AVFENEZBS
++ AVFENEZHS
++ AVFENEZFS
++ AVFA
++ AVFADB
++ AWFADB
++ AWFK
++ AWFKDB
++ AVFCE
++ AVFCEDB
++ AVFCEDBS
++ AWFCEDB
++ AWFCEDBS
++ AVFCH
++ AVFCHDB
++ AVFCHDBS
++ AWFCHDB
++ AWFCHDBS
++ AVFCHE
++ AVFCHEDB
++ AVFCHEDBS
++ AWFCHEDB
++ AWFCHEDBS
++ AWFC
++ AWFCDB
++ AVCDG
++ AVCDGB
++ AWCDGB
++ AVCDLG
++ AVCDLGB
++ AWCDLGB
++ AVCGD
++ AVCGDB
++ AWCGDB
++ AVCLGD
++ AVCLGDB
++ AWCLGDB
++ AVFD
++ AVFDDB
++ AWFDDB
++ AVLDE
++ AVLDEB
++ AWLDEB
++ AVLED
++ AVLEDB
++ AWLEDB
++ AVFM
++ AVFMDB
++ AWFMDB
++ AVFMA
++ AVFMADB
++ AWFMADB
++ AVFMS
++ AVFMSDB
++ AWFMSDB
++ AVFPSO
++ AVFPSODB
++ AWFPSODB
++ AVFLCDB
++ AWFLCDB
++ AVFLNDB
++ AWFLNDB
++ AVFLPDB
++ AWFLPDB
++ AVFSQ
++ AVFSQDB
++ AWFSQDB
++ AVFS
++ AVFSDB
++ AWFSDB
++ AVFTCI
++ AVFTCIDB
++ AWFTCIDB
++ AVGFM
++ AVGFMB
++ AVGFMH
++ AVGFMF
++ AVGFMG
++ AVGFMA
++ AVGFMAB
++ AVGFMAH
++ AVGFMAF
++ AVGFMAG
++ AVGEF
++ AVGEG
++ AVGBM
++ AVZERO
++ AVONE
++ AVGM
++ AVGMB
++ AVGMH
++ AVGMF
++ AVGMG
++ AVISTR
++ AVISTRB
++ AVISTRH
++ AVISTRF
++ AVISTRBS
++ AVISTRHS
++ AVISTRFS
++ AVL
++ AVLR
++ AVLREP
++ AVLREPB
++ AVLREPH
++ AVLREPF
++ AVLREPG
++ AVLC
++ AVLCB
++ AVLCH
++ AVLCF
++ AVLCG
++ AVLEH
++ AVLEF
++ AVLEG
++ AVLEB
++ AVLEIH
++ AVLEIF
++ AVLEIG
++ AVLEIB
++ AVFI
++ AVFIDB
++ AWFIDB
++ AVLGV
++ AVLGVB
++ AVLGVH
++ AVLGVF
++ AVLGVG
++ AVLLEZ
++ AVLLEZB
++ AVLLEZH
++ AVLLEZF
++ AVLLEZG
++ AVLM
++ AVLP
++ AVLPB
++ AVLPH
++ AVLPF
++ AVLPG
++ AVLBB
++ AVLVG
++ AVLVGB
++ AVLVGH
++ AVLVGF
++ AVLVGG
++ AVLVGP
++ AVLL
++ AVMX
++ AVMXB
++ AVMXH
++ AVMXF
++ AVMXG
++ AVMXL
++ AVMXLB
++ AVMXLH
++ AVMXLF
++ AVMXLG
++ AVMRH
++ AVMRHB
++ AVMRHH
++ AVMRHF
++ AVMRHG
++ AVMRL
++ AVMRLB
++ AVMRLH
++ AVMRLF
++ AVMRLG
++ AVMN
++ AVMNB
++ AVMNH
++ AVMNF
++ AVMNG
++ AVMNL
++ AVMNLB
++ AVMNLH
++ AVMNLF
++ AVMNLG
++ AVMAE
++ AVMAEB
++ AVMAEH
++ AVMAEF
++ AVMAH
++ AVMAHB
++ AVMAHH
++ AVMAHF
++ AVMALE
++ AVMALEB
++ AVMALEH
++ AVMALEF
++ AVMALH
++ AVMALHB
++ AVMALHH
++ AVMALHF
++ AVMALO
++ AVMALOB
++ AVMALOH
++ AVMALOF
++ AVMAL
++ AVMALB
++ AVMALHW
++ AVMALF
++ AVMAO
++ AVMAOB
++ AVMAOH
++ AVMAOF
++ AVME
++ AVMEB
++ AVMEH
++ AVMEF
++ AVMH
++ AVMHB
++ AVMHH
++ AVMHF
++ AVMLE
++ AVMLEB
++ AVMLEH
++ AVMLEF
++ AVMLH
++ AVMLHB
++ AVMLHH
++ AVMLHF
++ AVMLO
++ AVMLOB
++ AVMLOH
++ AVMLOF
++ AVML
++ AVMLB
++ AVMLHW
++ AVMLF
++ AVMO
++ AVMOB
++ AVMOH
++ AVMOF
++ AVNO
++ AVNOT
++ AVO
++ AVPK
++ AVPKH
++ AVPKF
++ AVPKG
++ AVPKLS
++ AVPKLSH
++ AVPKLSF
++ AVPKLSG
++ AVPKLSHS
++ AVPKLSFS
++ AVPKLSGS
++ AVPKS
++ AVPKSH
++ AVPKSF
++ AVPKSG
++ AVPKSHS
++ AVPKSFS
++ AVPKSGS
++ AVPERM
++ AVPDI
++ AVPOPCT
++ AVREP
++ AVREPB
++ AVREPH
++ AVREPF
++ AVREPG
++ AVREPI
++ AVREPIB
++ AVREPIH
++ AVREPIF
++ AVREPIG
++ AVSCEF
++ AVSCEG
++ AVSEL
++ AVSL
++ AVSLB
++ AVSLDB
++ AVSRA
++ AVSRAB
++ AVSRL
++ AVSRLB
++ AVSEG
++ AVSEGB
++ AVSEGH
++ AVSEGF
++ AVST
++ AVSTEH
++ AVSTEF
++ AVSTEG
++ AVSTEB
++ AVSTM
++ AVSTL
++ AVSTRC
++ AVSTRCB
++ AVSTRCH
++ AVSTRCF
++ AVSTRCBS
++ AVSTRCHS
++ AVSTRCFS
++ AVSTRCZB
++ AVSTRCZH
++ AVSTRCZF
++ AVSTRCZBS
++ AVSTRCZHS
++ AVSTRCZFS
++ AVS
++ AVSB
++ AVSH
++ AVSF
++ AVSG
++ AVSQ
++ AVSCBI
++ AVSCBIB
++ AVSCBIH
++ AVSCBIF
++ AVSCBIG
++ AVSCBIQ
++ AVSBCBI
++ AVSBCBIQ
++ AVSBI
++ AVSBIQ
++ AVSUMG
++ AVSUMGH
++ AVSUMGF
++ AVSUMQ
++ AVSUMQF
++ AVSUMQG
++ AVSUM
++ AVSUMB
++ AVSUMH
++ AVTM
++ AVUPH
++ AVUPHB
++ AVUPHH
++ AVUPHF
++ AVUPLH
++ AVUPLHB
++ AVUPLHH
++ AVUPLHF
++ AVUPLL
++ AVUPLLB
++ AVUPLLH
++ AVUPLLF
++ AVUPL
++ AVUPLB
++ AVUPLHW
++ AVUPLF
++
+ // binary
+ ABYTE
+ AWORD
@@ -14177,10 +16305,10 @@ index 0000000..a809306
+)
diff --git a/src/cmd/internal/obj/s390x/anames.go b/src/cmd/internal/obj/s390x/anames.go
new file mode 100644
-index 0000000..b34f092
+index 0000000..0cdc0e2
--- /dev/null
+++ b/src/cmd/internal/obj/s390x/anames.go
-@@ -0,0 +1,152 @@
+@@ -0,0 +1,658 @@
+// Generated by stringer -i a.out.go -o anames.go -p s390x
+// Do not edit.
+
@@ -14263,7 +16391,7 @@ index 0000000..b34f092
+ "FNMADDS",
+ "FNMSUB",
+ "FNMSUBS",
-+ "FRSP",
++ "LEDBR",
+ "LDEBR",
+ "FSUB",
+ "FSUBS",
@@ -14324,10 +16452,516 @@ index 0000000..b34f092
+ "LARL",
+ "LA",
+ "LAY",
++ "LMY",
++ "LMG",
++ "STMY",
++ "STMG",
+ "STCK",
+ "STCKC",
+ "STCKE",
+ "STCKF",
++ "CLEAR",
++ "VA",
++ "VAB",
++ "VAH",
++ "VAF",
++ "VAG",
++ "VAQ",
++ "VACC",
++ "VACCB",
++ "VACCH",
++ "VACCF",
++ "VACCG",
++ "VACCQ",
++ "VAC",
++ "VACQ",
++ "VACCC",
++ "VACCCQ",
++ "VN",
++ "VNC",
++ "VAVG",
++ "VAVGB",
++ "VAVGH",
++ "VAVGF",
++ "VAVGG",
++ "VAVGL",
++ "VAVGLB",
++ "VAVGLH",
++ "VAVGLF",
++ "VAVGLG",
++ "VCKSM",
++ "VCEQ",
++ "VCEQB",
++ "VCEQH",
++ "VCEQF",
++ "VCEQG",
++ "VCEQBS",
++ "VCEQHS",
++ "VCEQFS",
++ "VCEQGS",
++ "VCH",
++ "VCHB",
++ "VCHH",
++ "VCHF",
++ "VCHG",
++ "VCHBS",
++ "VCHHS",
++ "VCHFS",
++ "VCHGS",
++ "VCHL",
++ "VCHLB",
++ "VCHLH",
++ "VCHLF",
++ "VCHLG",
++ "VCHLBS",
++ "VCHLHS",
++ "VCHLFS",
++ "VCHLGS",
++ "VCLZ",
++ "VCLZB",
++ "VCLZH",
++ "VCLZF",
++ "VCLZG",
++ "VCTZ",
++ "VCTZB",
++ "VCTZH",
++ "VCTZF",
++ "VCTZG",
++ "VEC",
++ "VECB",
++ "VECH",
++ "VECF",
++ "VECG",
++ "VECL",
++ "VECLB",
++ "VECLH",
++ "VECLF",
++ "VECLG",
++ "VERIM",
++ "VERIMB",
++ "VERIMH",
++ "VERIMF",
++ "VERIMG",
++ "VERLL",
++ "VERLLB",
++ "VERLLH",
++ "VERLLF",
++ "VERLLG",
++ "VERLLV",
++ "VERLLVB",
++ "VERLLVH",
++ "VERLLVF",
++ "VERLLVG",
++ "VESLV",
++ "VESLVB",
++ "VESLVH",
++ "VESLVF",
++ "VESLVG",
++ "VESL",
++ "VESLB",
++ "VESLH",
++ "VESLF",
++ "VESLG",
++ "VESRA",
++ "VESRAB",
++ "VESRAH",
++ "VESRAF",
++ "VESRAG",
++ "VESRAV",
++ "VESRAVB",
++ "VESRAVH",
++ "VESRAVF",
++ "VESRAVG",
++ "VESRL",
++ "VESRLB",
++ "VESRLH",
++ "VESRLF",
++ "VESRLG",
++ "VESRLV",
++ "VESRLVB",
++ "VESRLVH",
++ "VESRLVF",
++ "VESRLVG",
++ "VX",
++ "VFAE",
++ "VFAEB",
++ "VFAEH",
++ "VFAEF",
++ "VFAEBS",
++ "VFAEHS",
++ "VFAEFS",
++ "VFAEZB",
++ "VFAEZH",
++ "VFAEZF",
++ "VFAEZBS",
++ "VFAEZHS",
++ "VFAEZFS",
++ "VFEE",
++ "VFEEB",
++ "VFEEH",
++ "VFEEF",
++ "VFEEBS",
++ "VFEEHS",
++ "VFEEFS",
++ "VFEEZB",
++ "VFEEZH",
++ "VFEEZF",
++ "VFEEZBS",
++ "VFEEZHS",
++ "VFEEZFS",
++ "VFENE",
++ "VFENEB",
++ "VFENEH",
++ "VFENEF",
++ "VFENEBS",
++ "VFENEHS",
++ "VFENEFS",
++ "VFENEZB",
++ "VFENEZH",
++ "VFENEZF",
++ "VFENEZBS",
++ "VFENEZHS",
++ "VFENEZFS",
++ "VFA",
++ "VFADB",
++ "WFADB",
++ "WFK",
++ "WFKDB",
++ "VFCE",
++ "VFCEDB",
++ "VFCEDBS",
++ "WFCEDB",
++ "WFCEDBS",
++ "VFCH",
++ "VFCHDB",
++ "VFCHDBS",
++ "WFCHDB",
++ "WFCHDBS",
++ "VFCHE",
++ "VFCHEDB",
++ "VFCHEDBS",
++ "WFCHEDB",
++ "WFCHEDBS",
++ "WFC",
++ "WFCDB",
++ "VCDG",
++ "VCDGB",
++ "WCDGB",
++ "VCDLG",
++ "VCDLGB",
++ "WCDLGB",
++ "VCGD",
++ "VCGDB",
++ "WCGDB",
++ "VCLGD",
++ "VCLGDB",
++ "WCLGDB",
++ "VFD",
++ "VFDDB",
++ "WFDDB",
++ "VLDE",
++ "VLDEB",
++ "WLDEB",
++ "VLED",
++ "VLEDB",
++ "WLEDB",
++ "VFM",
++ "VFMDB",
++ "WFMDB",
++ "VFMA",
++ "VFMADB",
++ "WFMADB",
++ "VFMS",
++ "VFMSDB",
++ "WFMSDB",
++ "VFPSO",
++ "VFPSODB",
++ "WFPSODB",
++ "VFLCDB",
++ "WFLCDB",
++ "VFLNDB",
++ "WFLNDB",
++ "VFLPDB",
++ "WFLPDB",
++ "VFSQ",
++ "VFSQDB",
++ "WFSQDB",
++ "VFS",
++ "VFSDB",
++ "WFSDB",
++ "VFTCI",
++ "VFTCIDB",
++ "WFTCIDB",
++ "VGFM",
++ "VGFMB",
++ "VGFMH",
++ "VGFMF",
++ "VGFMG",
++ "VGFMA",
++ "VGFMAB",
++ "VGFMAH",
++ "VGFMAF",
++ "VGFMAG",
++ "VGEF",
++ "VGEG",
++ "VGBM",
++ "VZERO",
++ "VONE",
++ "VGM",
++ "VGMB",
++ "VGMH",
++ "VGMF",
++ "VGMG",
++ "VISTR",
++ "VISTRB",
++ "VISTRH",
++ "VISTRF",
++ "VISTRBS",
++ "VISTRHS",
++ "VISTRFS",
++ "VL",
++ "VLR",
++ "VLREP",
++ "VLREPB",
++ "VLREPH",
++ "VLREPF",
++ "VLREPG",
++ "VLC",
++ "VLCB",
++ "VLCH",
++ "VLCF",
++ "VLCG",
++ "VLEH",
++ "VLEF",
++ "VLEG",
++ "VLEB",
++ "VLEIH",
++ "VLEIF",
++ "VLEIG",
++ "VLEIB",
++ "VFI",
++ "VFIDB",
++ "WFIDB",
++ "VLGV",
++ "VLGVB",
++ "VLGVH",
++ "VLGVF",
++ "VLGVG",
++ "VLLEZ",
++ "VLLEZB",
++ "VLLEZH",
++ "VLLEZF",
++ "VLLEZG",
++ "VLM",
++ "VLP",
++ "VLPB",
++ "VLPH",
++ "VLPF",
++ "VLPG",
++ "VLBB",
++ "VLVG",
++ "VLVGB",
++ "VLVGH",
++ "VLVGF",
++ "VLVGG",
++ "VLVGP",
++ "VLL",
++ "VMX",
++ "VMXB",
++ "VMXH",
++ "VMXF",
++ "VMXG",
++ "VMXL",
++ "VMXLB",
++ "VMXLH",
++ "VMXLF",
++ "VMXLG",
++ "VMRH",
++ "VMRHB",
++ "VMRHH",
++ "VMRHF",
++ "VMRHG",
++ "VMRL",
++ "VMRLB",
++ "VMRLH",
++ "VMRLF",
++ "VMRLG",
++ "VMN",
++ "VMNB",
++ "VMNH",
++ "VMNF",
++ "VMNG",
++ "VMNL",
++ "VMNLB",
++ "VMNLH",
++ "VMNLF",
++ "VMNLG",
++ "VMAE",
++ "VMAEB",
++ "VMAEH",
++ "VMAEF",
++ "VMAH",
++ "VMAHB",
++ "VMAHH",
++ "VMAHF",
++ "VMALE",
++ "VMALEB",
++ "VMALEH",
++ "VMALEF",
++ "VMALH",
++ "VMALHB",
++ "VMALHH",
++ "VMALHF",
++ "VMALO",
++ "VMALOB",
++ "VMALOH",
++ "VMALOF",
++ "VMAL",
++ "VMALB",
++ "VMALHW",
++ "VMALF",
++ "VMAO",
++ "VMAOB",
++ "VMAOH",
++ "VMAOF",
++ "VME",
++ "VMEB",
++ "VMEH",
++ "VMEF",
++ "VMH",
++ "VMHB",
++ "VMHH",
++ "VMHF",
++ "VMLE",
++ "VMLEB",
++ "VMLEH",
++ "VMLEF",
++ "VMLH",
++ "VMLHB",
++ "VMLHH",
++ "VMLHF",
++ "VMLO",
++ "VMLOB",
++ "VMLOH",
++ "VMLOF",
++ "VML",
++ "VMLB",
++ "VMLHW",
++ "VMLF",
++ "VMO",
++ "VMOB",
++ "VMOH",
++ "VMOF",
++ "VNO",
++ "VNOT",
++ "VO",
++ "VPK",
++ "VPKH",
++ "VPKF",
++ "VPKG",
++ "VPKLS",
++ "VPKLSH",
++ "VPKLSF",
++ "VPKLSG",
++ "VPKLSHS",
++ "VPKLSFS",
++ "VPKLSGS",
++ "VPKS",
++ "VPKSH",
++ "VPKSF",
++ "VPKSG",
++ "VPKSHS",
++ "VPKSFS",
++ "VPKSGS",
++ "VPERM",
++ "VPDI",
++ "VPOPCT",
++ "VREP",
++ "VREPB",
++ "VREPH",
++ "VREPF",
++ "VREPG",
++ "VREPI",
++ "VREPIB",
++ "VREPIH",
++ "VREPIF",
++ "VREPIG",
++ "VSCEF",
++ "VSCEG",
++ "VSEL",
++ "VSL",
++ "VSLB",
++ "VSLDB",
++ "VSRA",
++ "VSRAB",
++ "VSRL",
++ "VSRLB",
++ "VSEG",
++ "VSEGB",
++ "VSEGH",
++ "VSEGF",
++ "VST",
++ "VSTEH",
++ "VSTEF",
++ "VSTEG",
++ "VSTEB",
++ "VSTM",
++ "VSTL",
++ "VSTRC",
++ "VSTRCB",
++ "VSTRCH",
++ "VSTRCF",
++ "VSTRCBS",
++ "VSTRCHS",
++ "VSTRCFS",
++ "VSTRCZB",
++ "VSTRCZH",
++ "VSTRCZF",
++ "VSTRCZBS",
++ "VSTRCZHS",
++ "VSTRCZFS",
++ "VS",
++ "VSB",
++ "VSH",
++ "VSF",
++ "VSG",
++ "VSQ",
++ "VSCBI",
++ "VSCBIB",
++ "VSCBIH",
++ "VSCBIF",
++ "VSCBIG",
++ "VSCBIQ",
++ "VSBCBI",
++ "VSBCBIQ",
++ "VSBI",
++ "VSBIQ",
++ "VSUMG",
++ "VSUMGH",
++ "VSUMGF",
++ "VSUMQ",
++ "VSUMQF",
++ "VSUMQG",
++ "VSUM",
++ "VSUMB",
++ "VSUMH",
++ "VTM",
++ "VUPH",
++ "VUPHB",
++ "VUPHH",
++ "VUPHF",
++ "VUPLH",
++ "VUPLHB",
++ "VUPLHH",
++ "VUPLHF",
++ "VUPLL",
++ "VUPLLB",
++ "VUPLLH",
++ "VUPLLF",
++ "VUPL",
++ "VUPLB",
++ "VUPLHW",
++ "VUPLF",
+ "BYTE",
+ "WORD",
+ "DWORD",
@@ -14335,16 +16969,17 @@ index 0000000..b34f092
+}
diff --git a/src/cmd/internal/obj/s390x/anamesz.go b/src/cmd/internal/obj/s390x/anamesz.go
new file mode 100644
-index 0000000..75823c2
+index 0000000..bc5f969
--- /dev/null
+++ b/src/cmd/internal/obj/s390x/anamesz.go
-@@ -0,0 +1,35 @@
+@@ -0,0 +1,34 @@
+package s390x
+
+var cnamesz = []string{
+ "NONE",
+ "REG",
+ "FREG",
++ "VREG",
+ "AREG",
+ "ZCON",
+ "SCON",
@@ -14354,9 +16989,7 @@ index 0000000..75823c2
+ "LCON",
+ "DCON",
+ "SACON",
-+ "SECON",
+ "LACON",
-+ "LECON",
+ "DACON",
+ "SBRA",
+ "LBRA",
@@ -14367,19 +17000,19 @@ index 0000000..75823c2
+ "LOREG",
+ "TLS_LE",
+ "TLS_IE",
-+ "ANY",
+ "GOK",
+ "ADDR",
+ "GOTADDR",
+ "TEXTSIZE",
++ "ANY",
+ "NCLASS",
+}
diff --git a/src/cmd/internal/obj/s390x/asmz.go b/src/cmd/internal/obj/s390x/asmz.go
new file mode 100644
-index 0000000..7956f22
+index 0000000..82b07bb
--- /dev/null
+++ b/src/cmd/internal/obj/s390x/asmz.go
-@@ -0,0 +1,4017 @@
+@@ -0,0 +1,5177 @@
+// Based on cmd/internal/obj/ppc64/asm9.go.
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
@@ -14448,32 +17081,18 @@ index 0000000..7956f22
+ Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_REG, 13, 0},
+ Optab{AADD, C_REG, C_REG, C_NONE, C_REG, 2, 0},
+ Optab{AADD, C_REG, C_NONE, C_NONE, C_REG, 2, 0},
-+ Optab{AADD, C_ADDCON, C_REG, C_NONE, C_REG, 4, 0},
-+ Optab{AADD, C_ADDCON, C_NONE, C_NONE, C_REG, 4, 0},
-+ Optab{AADD, C_UCON, C_NONE, C_NONE, C_REG, 20, 0},
-+ Optab{AADD, C_UCON, C_REG, C_NONE, C_REG, 20, 0},
+ Optab{AADD, C_LCON, C_REG, C_NONE, C_REG, 22, 0},
+ Optab{AADD, C_LCON, C_NONE, C_NONE, C_REG, 22, 0},
+ Optab{AADDC, C_REG, C_REG, C_NONE, C_REG, 2, 0},
+ Optab{AADDC, C_REG, C_NONE, C_NONE, C_REG, 2, 0},
-+ Optab{AADDC, C_ADDCON, C_REG, C_NONE, C_REG, 4, 0},
-+ Optab{AADDC, C_ADDCON, C_NONE, C_NONE, C_REG, 4, 0},
+ Optab{AADDC, C_LCON, C_REG, C_NONE, C_REG, 22, 0},
+ Optab{AADDC, C_LCON, C_NONE, C_NONE, C_REG, 22, 0},
+ Optab{AAND, C_REG, C_REG, C_NONE, C_REG, 6, 0}, /* logical, no literal */
+ Optab{AAND, C_REG, C_NONE, C_NONE, C_REG, 6, 0},
-+ Optab{AAND, C_ANDCON, C_NONE, C_NONE, C_REG, 58, 0},
-+ Optab{AAND, C_ANDCON, C_REG, C_NONE, C_REG, 58, 0},
-+ Optab{AAND, C_UCON, C_NONE, C_NONE, C_REG, 59, 0},
-+ Optab{AAND, C_UCON, C_REG, C_NONE, C_REG, 59, 0},
+ Optab{AAND, C_LCON, C_NONE, C_NONE, C_REG, 23, 0},
+ Optab{AAND, C_LCON, C_REG, C_NONE, C_REG, 23, 0},
+ Optab{AMULLW, C_REG, C_REG, C_NONE, C_REG, 2, 0},
+ Optab{AMULLW, C_REG, C_NONE, C_NONE, C_REG, 2, 0},
-+ Optab{AMULLW, C_ADDCON, C_REG, C_NONE, C_REG, 4, 0},
-+ Optab{AMULLW, C_ADDCON, C_NONE, C_NONE, C_REG, 4, 0},
-+ Optab{AMULLW, C_ANDCON, C_REG, C_NONE, C_REG, 4, 0},
-+ Optab{AMULLW, C_ANDCON, C_NONE, C_NONE, C_REG, 4, 0},
+ Optab{AMULLW, C_LCON, C_REG, C_NONE, C_REG, 22, 0},
+ Optab{AMULLW, C_LCON, C_NONE, C_NONE, C_REG, 22, 0},
+ Optab{ASUBC, C_REG, C_REG, C_NONE, C_REG, 10, 0},
@@ -14482,10 +17101,6 @@ index 0000000..7956f22
+ Optab{ASUBC, C_REG, C_NONE, C_LCON, C_REG, 28, 0},
+ Optab{AOR, C_REG, C_REG, C_NONE, C_REG, 6, 0}, /* logical, literal not cc (or/xor) */
+ Optab{AOR, C_REG, C_NONE, C_NONE, C_REG, 6, 0},
-+ Optab{AOR, C_ANDCON, C_NONE, C_NONE, C_REG, 58, 0},
-+ Optab{AOR, C_ANDCON, C_REG, C_NONE, C_REG, 58, 0},
-+ Optab{AOR, C_UCON, C_NONE, C_NONE, C_REG, 59, 0},
-+ Optab{AOR, C_UCON, C_REG, C_NONE, C_REG, 59, 0},
+ Optab{AOR, C_LCON, C_NONE, C_NONE, C_REG, 23, 0},
+ Optab{AOR, C_LCON, C_REG, C_NONE, C_REG, 23, 0},
+ Optab{ADIVW, C_REG, C_REG, C_NONE, C_REG, 2, 0}, /* op r1[,r2],r3 */
@@ -14516,13 +17131,13 @@ index 0000000..7956f22
+ Optab{ARLDCL, C_REG, C_REG, C_LCON, C_REG, 14, 0},
+ Optab{ARLDCL, C_REG, C_NONE, C_LCON, C_REG, 14, 0},
+ Optab{AFADD, C_FREG, C_NONE, C_NONE, C_FREG, 2, 0},
-+ Optab{AFADD, C_FREG, C_REG, C_NONE, C_FREG, 2, 0},
++ Optab{AFADD, C_FREG, C_FREG, C_NONE, C_FREG, 2, 0},
+ Optab{AFABS, C_FREG, C_NONE, C_NONE, C_FREG, 33, 0},
+ Optab{AFABS, C_NONE, C_NONE, C_NONE, C_FREG, 33, 0},
+ Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_FREG, 33, 0},
-+ Optab{AFMADD, C_FREG, C_REG, C_FREG, C_FREG, 34, 0},
++ Optab{AFMADD, C_FREG, C_FREG, C_FREG, C_FREG, 34, 0},
+ Optab{AFMUL, C_FREG, C_NONE, C_NONE, C_FREG, 32, 0},
-+ Optab{AFMUL, C_FREG, C_REG, C_NONE, C_FREG, 32, 0},
++ Optab{AFMUL, C_FREG, C_FREG, C_NONE, C_FREG, 32, 0},
+ Optab{ACS, C_REG, C_REG, C_NONE, C_SOREG, 79, 0},
+ Optab{ACSG, C_REG, C_REG, C_NONE, C_SOREG, 79, 0},
+ Optab{ACEFBRA, C_REG, C_NONE, C_NONE, C_FREG, 82, 0},
@@ -14530,6 +17145,7 @@ index 0000000..7956f22
+ Optab{AMVC, C_SOREG, C_NONE, C_SCON, C_SOREG, 84, 0},
+ Optab{ALARL, C_LCON, C_NONE, C_NONE, C_REG, 85, 0},
+ Optab{ALA, C_SOREG, C_NONE, C_NONE, C_REG, 86, 0},
++ Optab{ALA, C_SAUTO, C_NONE, C_NONE, C_REG, 86, REGSP},
+ Optab{AEXRL, C_LCON, C_NONE, C_NONE, C_REG, 87, 0},
+ Optab{ASTCK, C_NONE, C_NONE, C_NONE, C_SAUTO, 88, REGSP},
+ Optab{ASTCK, C_NONE, C_NONE, C_NONE, C_SOREG, 88, 0},
@@ -14603,16 +17219,21 @@ index 0000000..7956f22
+ Optab{AMOVB, C_ADDR, C_NONE, C_NONE, C_REG, 76, 0},
+
+ /* store constant */
-+ Optab{AMOVD, C_SCON, C_NONE, C_NONE, C_SOREG, 92, 0},
-+ Optab{AMOVW, C_SCON, C_NONE, C_NONE, C_SOREG, 92, 0},
-+ Optab{AMOVWZ, C_SCON, C_NONE, C_NONE, C_SOREG, 92, 0},
-+ Optab{AMOVB, C_SCON, C_NONE, C_NONE, C_SOREG, 92, 0},
-+ Optab{AMOVBZ, C_SCON, C_NONE, C_NONE, C_SOREG, 92, 0},
-+ Optab{AMOVD, C_ADDCON, C_NONE, C_NONE, C_SOREG, 92, 0},
-+ Optab{AMOVW, C_ADDCON, C_NONE, C_NONE, C_SOREG, 92, 0},
-+ Optab{AMOVWZ, C_ADDCON, C_NONE, C_NONE, C_SOREG, 92, 0},
-+ Optab{AMOVB, C_ADDCON, C_NONE, C_NONE, C_SOREG, 92, 0},
-+ Optab{AMOVBZ, C_ADDCON, C_NONE, C_NONE, C_SOREG, 92, 0},
++ Optab{AMOVD, C_LCON, C_NONE, C_NONE, C_ADDR, 73, 0},
++ Optab{AMOVW, C_LCON, C_NONE, C_NONE, C_ADDR, 73, 0},
++ Optab{AMOVWZ, C_LCON, C_NONE, C_NONE, C_ADDR, 73, 0},
++ Optab{AMOVBZ, C_LCON, C_NONE, C_NONE, C_ADDR, 73, 0},
++ Optab{AMOVB, C_LCON, C_NONE, C_NONE, C_ADDR, 73, 0},
++ Optab{AMOVD, C_LCON, C_NONE, C_NONE, C_SAUTO, 72, REGSP},
++ Optab{AMOVW, C_LCON, C_NONE, C_NONE, C_SAUTO, 72, REGSP},
++ Optab{AMOVWZ, C_LCON, C_NONE, C_NONE, C_SAUTO, 72, REGSP},
++ Optab{AMOVB, C_LCON, C_NONE, C_NONE, C_SAUTO, 72, REGSP},
++ Optab{AMOVBZ, C_LCON, C_NONE, C_NONE, C_SAUTO, 72, REGSP},
++ Optab{AMOVD, C_LCON, C_NONE, C_NONE, C_SOREG, 72, 0},
++ Optab{AMOVW, C_LCON, C_NONE, C_NONE, C_SOREG, 72, 0},
++ Optab{AMOVWZ, C_LCON, C_NONE, C_NONE, C_SOREG, 72, 0},
++ Optab{AMOVB, C_LCON, C_NONE, C_NONE, C_SOREG, 72, 0},
++ Optab{AMOVBZ, C_LCON, C_NONE, C_NONE, C_SOREG, 72, 0},
+
+ /* load constant */
+ Optab{AMOVD, C_SACON, C_NONE, C_NONE, C_REG, 3, REGSP},
@@ -14627,7 +17248,8 @@ index 0000000..7956f22
+ Optab{AMOVB, C_ADDCON, C_NONE, C_NONE, C_REG, 3, 0},
+ Optab{AMOVBZ, C_ADDCON, C_NONE, C_NONE, C_REG, 3, 0},
+ Optab{AMOVB, C_SCON, C_NONE, C_NONE, C_REG, 3, 0},
-+ Optab{AMOVBZ, C_SCON, C_NONE, C_NONE, C_REG, 3, 0},
++ Optab{AMOVBZ, C_ANDCON, C_NONE, C_NONE, C_REG, 3, 0},
++ Optab{AMOVBZ, C_ADDCON, C_NONE, C_NONE, C_REG, 3, 0},
+
+ /* load unsigned/long constants (TODO: check) */
+ Optab{AMOVD, C_UCON, C_NONE, C_NONE, C_REG, 3, 0},
@@ -14705,6 +17327,118 @@ index 0000000..7956f22
+ Optab{AFCMPO, C_FREG, C_NONE, C_NONE, C_FREG, 70, 0},
+ Optab{AFCMPO, C_FREG, C_REG, C_NONE, C_FREG, 70, 0},
+
++ // macros
++ Optab{ACLEAR, C_LCON, C_NONE, C_NONE, C_LOREG, 96, 0},
++ Optab{ACLEAR, C_LCON, C_NONE, C_NONE, C_LAUTO, 96, REGSP},
++
++ ///////////////////////////////////////////////////////////////////////
++ // vector instructions
++ ///////////////////////////////////////////////////////////////////////
++
++ // VRX store
++ Optab{AVST, C_VREG, C_NONE, C_NONE, C_SOREG, 100, 0},
++ Optab{AVST, C_VREG, C_NONE, C_NONE, C_SAUTO, 100, REGSP},
++ Optab{AVSTEG, C_VREG, C_NONE, C_SCON, C_SOREG, 100, 0},
++ Optab{AVSTEG, C_VREG, C_NONE, C_SCON, C_SAUTO, 100, REGSP},
++
++ // VRX load
++ Optab{AVL, C_SOREG, C_NONE, C_NONE, C_VREG, 101, 0},
++ Optab{AVL, C_SAUTO, C_NONE, C_NONE, C_VREG, 101, REGSP},
++ Optab{AVLEG, C_SOREG, C_NONE, C_SCON, C_VREG, 101, 0},
++ Optab{AVLEG, C_SAUTO, C_NONE, C_SCON, C_VREG, 101, REGSP},
++
++ // VRV scatter
++ Optab{AVSCEG, C_VREG, C_NONE, C_SCON, C_SOREG, 102, 0},
++ Optab{AVSCEG, C_VREG, C_NONE, C_SCON, C_SAUTO, 102, REGSP},
++
++ // VRV gather
++ Optab{AVGEG, C_SOREG, C_NONE, C_SCON, C_VREG, 103, 0},
++ Optab{AVGEG, C_SAUTO, C_NONE, C_SCON, C_VREG, 103, REGSP},
++
++ // VRS element shift/rotate and load gr to/from vr element
++ Optab{AVESLG, C_SCON, C_VREG, C_NONE, C_VREG, 104, 0},
++ Optab{AVESLG, C_REG, C_VREG, C_NONE, C_VREG, 104, 0},
++ Optab{AVESLG, C_SCON, C_NONE, C_NONE, C_VREG, 104, 0},
++ Optab{AVESLG, C_REG, C_NONE, C_NONE, C_VREG, 104, 0},
++ Optab{AVLGVG, C_SCON, C_VREG, C_NONE, C_REG, 104, 0},
++ Optab{AVLGVG, C_REG, C_VREG, C_NONE, C_REG, 104, 0},
++ Optab{AVLVGG, C_SCON, C_REG, C_NONE, C_VREG, 104, 0},
++ Optab{AVLVGG, C_REG, C_REG, C_NONE, C_VREG, 104, 0},
++
++ // VRS store multiple
++ Optab{AVSTM, C_VREG, C_VREG, C_NONE, C_SOREG, 105, 0},
++ Optab{AVSTM, C_VREG, C_VREG, C_NONE, C_SAUTO, 105, REGSP},
++
++ // VRS load multiple
++ Optab{AVLM, C_SOREG, C_VREG, C_NONE, C_VREG, 106, 0},
++ Optab{AVLM, C_SAUTO, C_VREG, C_NONE, C_VREG, 106, REGSP},
++
++ // VRS store with length
++ Optab{AVSTL, C_VREG, C_NONE, C_REG, C_SOREG, 107, 0},
++ Optab{AVSTL, C_VREG, C_NONE, C_REG, C_SAUTO, 107, REGSP},
++
++ // VRS load with length
++ Optab{AVLL, C_SOREG, C_NONE, C_REG, C_VREG, 108, 0},
++ Optab{AVLL, C_SAUTO, C_NONE, C_REG, C_VREG, 108, REGSP},
++
++ // VRI-a
++ Optab{AVGBM, C_ANDCON, C_NONE, C_NONE, C_VREG, 109, 0},
++ Optab{AVZERO, C_NONE, C_NONE, C_NONE, C_VREG, 109, 0},
++ Optab{AVREPIG, C_ADDCON, C_NONE, C_NONE, C_VREG, 109, 0},
++ Optab{AVREPIG, C_SCON, C_NONE, C_NONE, C_VREG, 109, 0},
++ Optab{AVLEIG, C_ADDCON, C_NONE, C_SCON, C_VREG, 109, 0},
++ Optab{AVLEIG, C_SCON, C_NONE, C_SCON, C_VREG, 109, 0},
++
++ // VRI-b generate mask
++ Optab{AVGMG, C_SCON, C_NONE, C_SCON, C_VREG, 110, 0},
++
++ // VRI-c replicate
++ Optab{AVREPG, C_UCON, C_VREG, C_NONE, C_VREG, 111, 0},
++
++ // VRI-d element rotate and insert under mask and
++ // shift left double by byte
++ Optab{AVERIMG, C_VREG, C_VREG, C_SCON, C_VREG, 112, 0},
++ Optab{AVSLDB, C_VREG, C_VREG, C_SCON, C_VREG, 112, 0},
++
++ // VRI-d fp test data class immediate
++ Optab{AVFTCIDB, C_SCON, C_VREG, C_NONE, C_VREG, 113, 0},
++
++ // VRR-a load reg
++ Optab{AVLR, C_VREG, C_NONE, C_NONE, C_VREG, 114, 0},
++
++ // VRR-a compare
++ Optab{AVECG, C_VREG, C_NONE, C_NONE, C_VREG, 115, 0},
++
++ // VRR-b
++ Optab{AVCEQG, C_VREG, C_VREG, C_NONE, C_VREG, 117, 0},
++ Optab{AVFAEF, C_VREG, C_VREG, C_NONE, C_VREG, 117, 0},
++ Optab{AVPKSG, C_VREG, C_VREG, C_NONE, C_VREG, 117, 0},
++
++ // VRR-c
++ Optab{AVAQ, C_VREG, C_VREG, C_NONE, C_VREG, 118, 0},
++ Optab{AVAQ, C_VREG, C_NONE, C_NONE, C_VREG, 118, 0},
++ Optab{AVNOT, C_VREG, C_NONE, C_NONE, C_VREG, 118, 0},
++
++ // VRR-c shifts
++ Optab{AVERLLVG, C_VREG, C_VREG, C_NONE, C_VREG, 119, 0},
++ Optab{AVERLLVG, C_VREG, C_NONE, C_NONE, C_VREG, 119, 0},
++
++ // VRR-d
++ // 2 3 1 4
++ Optab{AVACQ, C_VREG, C_VREG, C_VREG, C_VREG, 120, 0},
++
++ // VRR-e
++ Optab{AVSEL, C_VREG, C_VREG, C_VREG, C_VREG, 121, 0},
++
++ // VRR-f
++ Optab{AVLVGP, C_REG, C_REG, C_NONE, C_VREG, 122, 0},
++
++ // load/store multiple
++ Optab{ASTMG, C_REG, C_REG, C_NONE, C_LOREG, 97, 0},
++ Optab{ASTMG, C_REG, C_REG, C_NONE, C_LAUTO, 97, REGSP},
++ Optab{ALMG, C_LOREG, C_REG, C_NONE, C_REG, 98, 0},
++ Optab{ALMG, C_LAUTO, C_REG, C_NONE, C_REG, 98, REGSP},
++
+ Optab{obj.AUNDEF, C_NONE, C_NONE, C_NONE, C_NONE, 78, 0},
+ Optab{obj.APCDATA, C_LCON, C_NONE, C_NONE, C_LCON, 0, 0},
+ Optab{obj.AFUNCDATA, C_SCON, C_NONE, C_NONE, C_ADDR, 0, 0},
@@ -14792,6 +17526,9 @@ index 0000000..7956f22
+ if REG_AR0 <= a.Reg && a.Reg <= REG_AR15 {
+ return C_AREG
+ }
++ if REG_V0 <= a.Reg && a.Reg <= REG_V31 {
++ return C_VREG
++ }
+ return C_GOK
+
+ case obj.TYPE_MEM:
@@ -14866,14 +17603,11 @@ index 0000000..7956f22
+ if s == nil {
+ break
+ }
++ ctxt.Instoffset = s.Value + a.Offset
+ if s.Type == obj.SCONST {
-+ ctxt.Instoffset = s.Value + a.Offset
+ goto consize
+ }
+
-+ ctxt.Instoffset = s.Value + a.Offset
-+
-+ /* not sure why this barfs */
+ return C_LCON
+
+ case obj.NAME_AUTO:
@@ -14959,7 +17693,15 @@ index 0000000..7956f22
+ a4--
+ a2 := C_NONE
+ if p.Reg != 0 {
-+ a2 = C_REG
++ if REG_R0 <= p.Reg && p.Reg <= REG_R15 {
++ a2 = C_REG
++ } else if REG_V0 <= p.Reg && p.Reg <= REG_V31 {
++ a2 = C_VREG
++ } else if REG_F0 <= p.Reg && p.Reg <= REG_F15 {
++ a2 = C_FREG
++ } else if REG_AR0 <= p.Reg && p.Reg <= REG_AR15 {
++ a2 = C_AREG
++ }
+ }
+
+ r0 := p.As & obj.AMask
@@ -15013,7 +17755,7 @@ index 0000000..7956f22
+ }
+
+ case C_UCON:
-+ if b == C_ZCON {
++ if b == C_ZCON || b == C_SCON {
+ return true
+ }
+
@@ -15166,6 +17908,14 @@ index 0000000..7956f22
+ opset(ASTCKE, r0)
+ opset(ASTCKF, r0)
+
++ case ACLEAR:
++
++ case ASTMG:
++ opset(ASTMY, r0)
++
++ case ALMG:
++ opset(ALMY, r0)
++
+ case AAND: /* logical op Rb,Rs,Ra; no literal */
+ opset(AANDN, r0)
+ opset(ANAND, r0)
@@ -15197,7 +17947,7 @@ index 0000000..7956f22
+ case AFABS: /* fop [s,]d */
+ opset(AFNABS, r0)
+ opset(AFNEG, r0)
-+ opset(AFRSP, r0)
++ opset(ALEDBR, r0)
+ opset(ALDEBR, r0)
+ opset(AFSQRT, r0)
+ opset(AFSQRTS, r0)
@@ -15304,6 +18054,430 @@ index 0000000..7956f22
+ opset(ACMPUBLT, r0)
+ opset(ACMPUBNE, r0)
+
++ case AVL:
++ opset(AVLLEZB, r0)
++ opset(AVLLEZH, r0)
++ opset(AVLLEZF, r0)
++ opset(AVLLEZG, r0)
++ opset(AVLREPB, r0)
++ opset(AVLREPH, r0)
++ opset(AVLREPF, r0)
++ opset(AVLREPG, r0)
++
++ case AVST:
++
++ case AVLEG:
++ opset(AVLBB, r0)
++ opset(AVLEB, r0)
++ opset(AVLEH, r0)
++ opset(AVLEF, r0)
++ opset(AVLEG, r0)
++ opset(AVLREP, r0)
++
++ case AVSTEG:
++ opset(AVSTEB, r0)
++ opset(AVSTEH, r0)
++ opset(AVSTEF, r0)
++
++ case AVSCEG:
++ opset(AVSCEF, r0)
++
++ case AVGEG:
++ opset(AVGEF, r0)
++
++ case AVESLG:
++ opset(AVESLB, r0)
++ opset(AVESLH, r0)
++ opset(AVESLF, r0)
++ opset(AVERLLB, r0)
++ opset(AVERLLH, r0)
++ opset(AVERLLF, r0)
++ opset(AVERLLG, r0)
++ opset(AVESRAB, r0)
++ opset(AVESRAH, r0)
++ opset(AVESRAF, r0)
++ opset(AVESRAG, r0)
++ opset(AVESRLB, r0)
++ opset(AVESRLH, r0)
++ opset(AVESRLF, r0)
++ opset(AVESRLG, r0)
++
++ case AVLGVG:
++ opset(AVLGVB, r0)
++ opset(AVLGVH, r0)
++ opset(AVLGVF, r0)
++
++ case AVLVGG:
++ opset(AVLVGB, r0)
++ opset(AVLVGH, r0)
++ opset(AVLVGF, r0)
++
++ case AVLL:
++
++ case AVSTL:
++
++ case AVLM:
++
++ case AVSTM:
++
++ case AVGBM:
++
++ case AVZERO:
++ opset(AVONE, r0)
++
++ case AVREPIG:
++ opset(AVREPIB, r0)
++ opset(AVREPIH, r0)
++ opset(AVREPIF, r0)
++
++ case AVLEIG:
++ opset(AVLEIB, r0)
++ opset(AVLEIH, r0)
++ opset(AVLEIF, r0)
++
++ case AVGMG:
++ opset(AVGMB, r0)
++ opset(AVGMH, r0)
++ opset(AVGMF, r0)
++
++ case AVREPG:
++ opset(AVREPB, r0)
++ opset(AVREPH, r0)
++ opset(AVREPF, r0)
++
++ case AVERIMG:
++ opset(AVERIMB, r0)
++ opset(AVERIMH, r0)
++ opset(AVERIMF, r0)
++
++ case AVSLDB:
++
++ case AVFTCIDB:
++ opset(AWFTCIDB, r0)
++
++ case AVLR:
++ opset(AVUPHB, r0)
++ opset(AVUPHH, r0)
++ opset(AVUPHF, r0)
++ opset(AVUPLHB, r0)
++ opset(AVUPLHH, r0)
++ opset(AVUPLHF, r0)
++ opset(AVUPLB, r0)
++ opset(AVUPLHW, r0)
++ opset(AVUPLF, r0)
++ opset(AVUPLLB, r0)
++ opset(AVUPLLH, r0)
++ opset(AVUPLLF, r0)
++ opset(AVCLZB, r0)
++ opset(AVCLZH, r0)
++ opset(AVCLZF, r0)
++ opset(AVCLZG, r0)
++ opset(AVCTZB, r0)
++ opset(AVCTZH, r0)
++ opset(AVCTZF, r0)
++ opset(AVCTZG, r0)
++ opset(AVLDEB, r0)
++ opset(AWLDEB, r0)
++ opset(AVFLCDB, r0)
++ opset(AWFLCDB, r0)
++ opset(AVFLNDB, r0)
++ opset(AWFLNDB, r0)
++ opset(AVFLPDB, r0)
++ opset(AWFLPDB, r0)
++ opset(AVFSQDB, r0)
++ opset(AWFSQDB, r0)
++ opset(AVISTRB, r0)
++ opset(AVISTRH, r0)
++ opset(AVISTRF, r0)
++ opset(AVISTRBS, r0)
++ opset(AVISTRHS, r0)
++ opset(AVISTRFS, r0)
++ opset(AVLCB, r0)
++ opset(AVLCH, r0)
++ opset(AVLCF, r0)
++ opset(AVLCG, r0)
++ opset(AVLPB, r0)
++ opset(AVLPH, r0)
++ opset(AVLPF, r0)
++ opset(AVLPG, r0)
++ opset(AVPOPCT, r0)
++ opset(AVSEGB, r0)
++ opset(AVSEGH, r0)
++ opset(AVSEGF, r0)
++
++ case AVECG:
++ opset(AVECB, r0)
++ opset(AVECH, r0)
++ opset(AVECF, r0)
++ opset(AVECLB, r0)
++ opset(AVECLH, r0)
++ opset(AVECLF, r0)
++ opset(AVECLG, r0)
++ opset(AWFCDB, r0)
++ opset(AWFKDB, r0)
++
++ case AVCEQG:
++ opset(AVCEQB, r0)
++ opset(AVCEQH, r0)
++ opset(AVCEQF, r0)
++ opset(AVCEQBS, r0)
++ opset(AVCEQHS, r0)
++ opset(AVCEQFS, r0)
++ opset(AVCEQGS, r0)
++ opset(AVCHB, r0)
++ opset(AVCHH, r0)
++ opset(AVCHF, r0)
++ opset(AVCHG, r0)
++ opset(AVCHBS, r0)
++ opset(AVCHHS, r0)
++ opset(AVCHFS, r0)
++ opset(AVCHGS, r0)
++ opset(AVCHLB, r0)
++ opset(AVCHLH, r0)
++ opset(AVCHLF, r0)
++ opset(AVCHLG, r0)
++ opset(AVCHLBS, r0)
++ opset(AVCHLHS, r0)
++ opset(AVCHLFS, r0)
++ opset(AVCHLGS, r0)
++
++ case AVFAEF:
++ opset(AVFAEB, r0)
++ opset(AVFAEH, r0)
++ opset(AVFAEBS, r0)
++ opset(AVFAEHS, r0)
++ opset(AVFAEFS, r0)
++ opset(AVFAEZB, r0)
++ opset(AVFAEZH, r0)
++ opset(AVFAEZF, r0)
++ opset(AVFAEZBS, r0)
++ opset(AVFAEZHS, r0)
++ opset(AVFAEZFS, r0)
++ opset(AVFEEB, r0)
++ opset(AVFEEH, r0)
++ opset(AVFEEF, r0)
++ opset(AVFEEBS, r0)
++ opset(AVFEEHS, r0)
++ opset(AVFEEFS, r0)
++ opset(AVFEEZB, r0)
++ opset(AVFEEZH, r0)
++ opset(AVFEEZF, r0)
++ opset(AVFEEZBS, r0)
++ opset(AVFEEZHS, r0)
++ opset(AVFEEZFS, r0)
++ opset(AVFENEB, r0)
++ opset(AVFENEH, r0)
++ opset(AVFENEF, r0)
++ opset(AVFENEBS, r0)
++ opset(AVFENEHS, r0)
++ opset(AVFENEFS, r0)
++ opset(AVFENEZB, r0)
++ opset(AVFENEZH, r0)
++ opset(AVFENEZF, r0)
++ opset(AVFENEZBS, r0)
++ opset(AVFENEZHS, r0)
++ opset(AVFENEZFS, r0)
++
++ case AVPKSG:
++ opset(AVPKSH, r0)
++ opset(AVPKSF, r0)
++ opset(AVPKSHS, r0)
++ opset(AVPKSFS, r0)
++ opset(AVPKSGS, r0)
++ opset(AVPKLSH, r0)
++ opset(AVPKLSF, r0)
++ opset(AVPKLSG, r0)
++ opset(AVPKLSHS, r0)
++ opset(AVPKLSFS, r0)
++ opset(AVPKLSGS, r0)
++
++ case AVAQ:
++ opset(AVAB, r0)
++ opset(AVAH, r0)
++ opset(AVAF, r0)
++ opset(AVAG, r0)
++ opset(AVACCB, r0)
++ opset(AVACCH, r0)
++ opset(AVACCF, r0)
++ opset(AVACCG, r0)
++ opset(AVACCQ, r0)
++ opset(AVN, r0)
++ opset(AVNC, r0)
++ opset(AVAVGB, r0)
++ opset(AVAVGH, r0)
++ opset(AVAVGF, r0)
++ opset(AVAVGG, r0)
++ opset(AVAVGLB, r0)
++ opset(AVAVGLH, r0)
++ opset(AVAVGLF, r0)
++ opset(AVAVGLG, r0)
++ opset(AVCKSM, r0)
++ opset(AVX, r0)
++ opset(AVFADB, r0)
++ opset(AWFADB, r0)
++ opset(AVFCEDB, r0)
++ opset(AVFCEDBS, r0)
++ opset(AWFCEDB, r0)
++ opset(AWFCEDBS, r0)
++ opset(AVFCHDB, r0)
++ opset(AVFCHDBS, r0)
++ opset(AWFCHDB, r0)
++ opset(AWFCHDBS, r0)
++ opset(AVFCHEDB, r0)
++ opset(AVFCHEDBS, r0)
++ opset(AWFCHEDB, r0)
++ opset(AWFCHEDBS, r0)
++ opset(AVFMDB, r0)
++ opset(AWFMDB, r0)
++ opset(AVGFMB, r0)
++ opset(AVGFMH, r0)
++ opset(AVGFMF, r0)
++ opset(AVGFMG, r0)
++ opset(AVMXB, r0)
++ opset(AVMXH, r0)
++ opset(AVMXF, r0)
++ opset(AVMXG, r0)
++ opset(AVMXLB, r0)
++ opset(AVMXLH, r0)
++ opset(AVMXLF, r0)
++ opset(AVMXLG, r0)
++ opset(AVMNB, r0)
++ opset(AVMNH, r0)
++ opset(AVMNF, r0)
++ opset(AVMNG, r0)
++ opset(AVMNLB, r0)
++ opset(AVMNLH, r0)
++ opset(AVMNLF, r0)
++ opset(AVMNLG, r0)
++ opset(AVMRHB, r0)
++ opset(AVMRHH, r0)
++ opset(AVMRHF, r0)
++ opset(AVMRHG, r0)
++ opset(AVMRLB, r0)
++ opset(AVMRLH, r0)
++ opset(AVMRLF, r0)
++ opset(AVMRLG, r0)
++ opset(AVMEB, r0)
++ opset(AVMEH, r0)
++ opset(AVMEF, r0)
++ opset(AVMLEB, r0)
++ opset(AVMLEH, r0)
++ opset(AVMLEF, r0)
++ opset(AVMOB, r0)
++ opset(AVMOH, r0)
++ opset(AVMOF, r0)
++ opset(AVMLOB, r0)
++ opset(AVMLOH, r0)
++ opset(AVMLOF, r0)
++ opset(AVMHB, r0)
++ opset(AVMHH, r0)
++ opset(AVMHF, r0)
++ opset(AVMLHB, r0)
++ opset(AVMLHH, r0)
++ opset(AVMLHF, r0)
++ opset(AVMLH, r0)
++ opset(AVMLHW, r0)
++ opset(AVMLF, r0)
++ opset(AVNO, r0)
++ opset(AVO, r0)
++ opset(AVPKH, r0)
++ opset(AVPKF, r0)
++ opset(AVPKG, r0)
++ opset(AVSUMGH, r0)
++ opset(AVSUMGF, r0)
++ opset(AVSUMQF, r0)
++ opset(AVSUMQG, r0)
++ opset(AVSUMB, r0)
++ opset(AVSUMH, r0)
++
++ case AVNOT:
++
++ case AVERLLVG:
++ opset(AVERLLVB, r0)
++ opset(AVERLLVH, r0)
++ opset(AVERLLVF, r0)
++ opset(AVESLVB, r0)
++ opset(AVESLVH, r0)
++ opset(AVESLVF, r0)
++ opset(AVESLVG, r0)
++ opset(AVESRAVB, r0)
++ opset(AVESRAVH, r0)
++ opset(AVESRAVF, r0)
++ opset(AVESRAVG, r0)
++ opset(AVESRLVB, r0)
++ opset(AVESRLVH, r0)
++ opset(AVESRLVF, r0)
++ opset(AVESRLVG, r0)
++ opset(AVFDDB, r0)
++ opset(AWFDDB, r0)
++ opset(AVFSDB, r0)
++ opset(AWFSDB, r0)
++ opset(AVSL, r0)
++ opset(AVSLB, r0)
++ opset(AVSRA, r0)
++ opset(AVSRAB, r0)
++ opset(AVSRL, r0)
++ opset(AVSRLB, r0)
++ opset(AVSF, r0)
++ opset(AVSG, r0)
++ opset(AVSQ, r0)
++ opset(AVSCBIB, r0)
++ opset(AVSCBIH, r0)
++ opset(AVSCBIF, r0)
++ opset(AVSCBIG, r0)
++ opset(AVSCBIQ, r0)
++
++ case AVACQ:
++ opset(AVACCCQ, r0)
++ opset(AVGFMAB, r0)
++ opset(AVGFMAH, r0)
++ opset(AVGFMAF, r0)
++ opset(AVGFMAG, r0)
++ opset(AVMALB, r0)
++ opset(AVMALHW, r0)
++ opset(AVMALF, r0)
++ opset(AVMAHB, r0)
++ opset(AVMAHH, r0)
++ opset(AVMAHF, r0)
++ opset(AVMALHB, r0)
++ opset(AVMALHH, r0)
++ opset(AVMALHF, r0)
++ opset(AVMAEB, r0)
++ opset(AVMAEH, r0)
++ opset(AVMAEF, r0)
++ opset(AVMALEB, r0)
++ opset(AVMALEH, r0)
++ opset(AVMALEF, r0)
++ opset(AVMAOB, r0)
++ opset(AVMAOH, r0)
++ opset(AVMAOF, r0)
++ opset(AVMALOB, r0)
++ opset(AVMALOH, r0)
++ opset(AVMALOF, r0)
++ opset(AVSTRCB, r0)
++ opset(AVSTRCH, r0)
++ opset(AVSTRCF, r0)
++ opset(AVSTRCBS, r0)
++ opset(AVSTRCHS, r0)
++ opset(AVSTRCFS, r0)
++ opset(AVSTRCZB, r0)
++ opset(AVSTRCZH, r0)
++ opset(AVSTRCZF, r0)
++ opset(AVSTRCZBS, r0)
++ opset(AVSTRCZHS, r0)
++ opset(AVSTRCZFS, r0)
++ opset(AVSBCBIQ, r0)
++ opset(AVSBIQ, r0)
++
++ case AVSEL:
++ opset(AVFMADB, r0)
++ opset(AWFMADB, r0)
++ opset(AVFMSDB, r0)
++ opset(AWFMSDB, r0)
++ opset(AVPERM, r0)
++
++ case AVLVGP:
++
+ case AADD,
+ AMOVW,
+ /* load/store/move word with sign extension; special 32-bit move; move 32-bit literals */
@@ -16315,6 +19489,160 @@ index 0000000..7956f22
+ OP_XSCH uint32 = 0xB276 // FORMAT_S CANCEL SUBCHANNEL
+ OP_XY uint32 = 0xE357 // FORMAT_RXY1 EXCLUSIVE OR (32)
+ OP_ZAP uint32 = 0xF800 // FORMAT_SS2 ZERO AND ADD
++
++ // added in z13
++ OP_CXPT uint32 = 0xEDAF // RSL-b CONVERT FROM PACKED (to extended DFP)
++ OP_CDPT uint32 = 0xEDAE // RSL-b CONVERT FROM PACKED (to long DFP)
++ OP_CPXT uint32 = 0xEDAD // RSL-b CONVERT TO PACKED (from extended DFP)
++ OP_CPDT uint32 = 0xEDAC // RSL-b CONVERT TO PACKED (from long DFP)
++ OP_LZRF uint32 = 0xE33B // RXY-a LOAD AND ZERO RIGHTMOST BYTE (32)
++ OP_LZRG uint32 = 0xE32A // RXY-a LOAD AND ZERO RIGHTMOST BYTE (64)
++ OP_LCCB uint32 = 0xE727 // RXE LOAD COUNT TO BLOCK BOUNDARY
++ OP_LOCHHI uint32 = 0xEC4E // RIE-g LOAD HALFWORD HIGH IMMEDIATE ON CONDITION (32←16)
++ OP_LOCHI uint32 = 0xEC42 // RIE-g LOAD HALFWORD IMMEDIATE ON CONDITION (32←16)
++ OP_LOCGHI uint32 = 0xEC46 // RIE-g LOAD HALFWORD IMMEDIATE ON CONDITION (64←16)
++ OP_LOCFH uint32 = 0xEBE0 // RSY-b LOAD HIGH ON CONDITION (32)
++ OP_LOCFHR uint32 = 0xB9E0 // RRF-c LOAD HIGH ON CONDITION (32)
++ OP_LLZRGF uint32 = 0xE33A // RXY-a LOAD LOGICAL AND ZERO RIGHTMOST BYTE (64←32)
++ OP_STOCFH uint32 = 0xEBE1 // RSY-b STORE HIGH ON CONDITION
++ OP_VA uint32 = 0xE7F3 // VRR-c VECTOR ADD
++ OP_VACC uint32 = 0xE7F1 // VRR-c VECTOR ADD COMPUTE CARRY
++ OP_VAC uint32 = 0xE7BB // VRR-d VECTOR ADD WITH CARRY
++ OP_VACCC uint32 = 0xE7B9 // VRR-d VECTOR ADD WITH CARRY COMPUTE CARRY
++ OP_VN uint32 = 0xE768 // VRR-c VECTOR AND
++ OP_VNC uint32 = 0xE769 // VRR-c VECTOR AND WITH COMPLEMENT
++ OP_VAVG uint32 = 0xE7F2 // VRR-c VECTOR AVERAGE
++ OP_VAVGL uint32 = 0xE7F0 // VRR-c VECTOR AVERAGE LOGICAL
++ OP_VCKSM uint32 = 0xE766 // VRR-c VECTOR CHECKSUM
++ OP_VCEQ uint32 = 0xE7F8 // VRR-b VECTOR COMPARE EQUAL
++ OP_VCH uint32 = 0xE7FB // VRR-b VECTOR COMPARE HIGH
++ OP_VCHL uint32 = 0xE7F9 // VRR-b VECTOR COMPARE HIGH LOGICAL
++ OP_VCLZ uint32 = 0xE753 // VRR-a VECTOR COUNT LEADING ZEROS
++ OP_VCTZ uint32 = 0xE752 // VRR-a VECTOR COUNT TRAILING ZEROS
++ OP_VEC uint32 = 0xE7DB // VRR-a VECTOR ELEMENT COMPARE
++ OP_VECL uint32 = 0xE7D9 // VRR-a VECTOR ELEMENT COMPARE LOGICAL
++ OP_VERIM uint32 = 0xE772 // VRI-d VECTOR ELEMENT ROTATE AND INSERT UNDER MASK
++ OP_VERLL uint32 = 0xE733 // VRS-a VECTOR ELEMENT ROTATE LEFT LOGICAL
++ OP_VERLLV uint32 = 0xE773 // VRR-c VECTOR ELEMENT ROTATE LEFT LOGICAL
++ OP_VESLV uint32 = 0xE770 // VRR-c VECTOR ELEMENT SHIFT LEFT
++ OP_VESL uint32 = 0xE730 // VRS-a VECTOR ELEMENT SHIFT LEFT
++ OP_VESRA uint32 = 0xE73A // VRS-a VECTOR ELEMENT SHIFT RIGHT ARITHMETIC
++ OP_VESRAV uint32 = 0xE77A // VRR-c VECTOR ELEMENT SHIFT RIGHT ARITHMETIC
++ OP_VESRL uint32 = 0xE738 // VRS-a VECTOR ELEMENT SHIFT RIGHT LOGICAL
++ OP_VESRLV uint32 = 0xE778 // VRR-c VECTOR ELEMENT SHIFT RIGHT LOGICAL
++ OP_VX uint32 = 0xE76D // VRR-c VECTOR EXCLUSIVE OR
++ OP_VFAE uint32 = 0xE782 // VRR-b VECTOR FIND ANY ELEMENT EQUAL
++ OP_VFEE uint32 = 0xE780 // VRR-b VECTOR FIND ELEMENT EQUAL
++ OP_VFENE uint32 = 0xE781 // VRR-b VECTOR FIND ELEMENT NOT EQUAL
++ OP_VFA uint32 = 0xE7E3 // VRR-c VECTOR FP ADD
++ OP_WFK uint32 = 0xE7CA // VRR-a VECTOR FP COMPARE AND SIGNAL SCALAR
++ OP_VFCE uint32 = 0xE7E8 // VRR-c VECTOR FP COMPARE EQUAL
++ OP_VFCH uint32 = 0xE7EB // VRR-c VECTOR FP COMPARE HIGH
++ OP_VFCHE uint32 = 0xE7EA // VRR-c VECTOR FP COMPARE HIGH OR EQUAL
++ OP_WFC uint32 = 0xE7CB // VRR-a VECTOR FP COMPARE SCALAR
++ OP_VCDG uint32 = 0xE7C3 // VRR-a VECTOR FP CONVERT FROM FIXED 64-BIT
++ OP_VCDLG uint32 = 0xE7C1 // VRR-a VECTOR FP CONVERT FROM LOGICAL 64-BIT
++ OP_VCGD uint32 = 0xE7C2 // VRR-a VECTOR FP CONVERT TO FIXED 64-BIT
++ OP_VCLGD uint32 = 0xE7C0 // VRR-a VECTOR FP CONVERT TO LOGICAL 64-BIT
++ OP_VFD uint32 = 0xE7E5 // VRR-c VECTOR FP DIVIDE
++ OP_VLDE uint32 = 0xE7C4 // VRR-a VECTOR FP LOAD LENGTHENED
++ OP_VLED uint32 = 0xE7C5 // VRR-a VECTOR FP LOAD ROUNDED
++ OP_VFM uint32 = 0xE7E7 // VRR-c VECTOR FP MULTIPLY
++ OP_VFMA uint32 = 0xE78F // VRR-e VECTOR FP MULTIPLY AND ADD
++ OP_VFMS uint32 = 0xE78E // VRR-e VECTOR FP MULTIPLY AND SUBTRACT
++ OP_VFPSO uint32 = 0xE7CC // VRR-a VECTOR FP PERFORM SIGN OPERATION
++ OP_VFSQ uint32 = 0xE7CE // VRR-a VECTOR FP SQUARE ROOT
++ OP_VFS uint32 = 0xE7E2 // VRR-c VECTOR FP SUBTRACT
++ OP_VFTCI uint32 = 0xE74A // VRI-e VECTOR FP TEST DATA CLASS IMMEDIATE
++ OP_VGFM uint32 = 0xE7B4 // VRR-c VECTOR GALOIS FIELD MULTIPLY SUM
++ OP_VGFMA uint32 = 0xE7BC // VRR-d VECTOR GALOIS FIELD MULTIPLY SUM AND ACCUMULATE
++ OP_VGEF uint32 = 0xE713 // VRV VECTOR GATHER ELEMENT (32)
++ OP_VGEG uint32 = 0xE712 // VRV VECTOR GATHER ELEMENT (64)
++ OP_VGBM uint32 = 0xE744 // VRI-a VECTOR GENERATE BYTE MASK
++ OP_VGM uint32 = 0xE746 // VRI-b VECTOR GENERATE MASK
++ OP_VISTR uint32 = 0xE75C // VRR-a VECTOR ISOLATE STRING
++ OP_VL uint32 = 0xE706 // VRX VECTOR LOAD
++ OP_VLR uint32 = 0xE756 // VRR-a VECTOR LOAD
++ OP_VLREP uint32 = 0xE705 // VRX VECTOR LOAD AND REPLICATE
++ OP_VLC uint32 = 0xE7DE // VRR-a VECTOR LOAD COMPLEMENT
++ OP_VLEH uint32 = 0xE701 // VRX VECTOR LOAD ELEMENT (16)
++ OP_VLEF uint32 = 0xE703 // VRX VECTOR LOAD ELEMENT (32)
++ OP_VLEG uint32 = 0xE702 // VRX VECTOR LOAD ELEMENT (64)
++ OP_VLEB uint32 = 0xE700 // VRX VECTOR LOAD ELEMENT (8)
++ OP_VLEIH uint32 = 0xE741 // VRI-a VECTOR LOAD ELEMENT IMMEDIATE (16)
++ OP_VLEIF uint32 = 0xE743 // VRI-a VECTOR LOAD ELEMENT IMMEDIATE (32)
++ OP_VLEIG uint32 = 0xE742 // VRI-a VECTOR LOAD ELEMENT IMMEDIATE (64)
++ OP_VLEIB uint32 = 0xE740 // VRI-a VECTOR LOAD ELEMENT IMMEDIATE (8)
++ OP_VFI uint32 = 0xE7C7 // VRR-a VECTOR LOAD FP INTEGER
++ OP_VLGV uint32 = 0xE721 // VRS-c VECTOR LOAD GR FROM VR ELEMENT
++ OP_VLLEZ uint32 = 0xE704 // VRX VECTOR LOAD LOGICAL ELEMENT AND ZERO
++ OP_VLM uint32 = 0xE736 // VRS-a VECTOR LOAD MULTIPLE
++ OP_VLP uint32 = 0xE7DF // VRR-a VECTOR LOAD POSITIVE
++ OP_VLBB uint32 = 0xE707 // VRX VECTOR LOAD TO BLOCK BOUNDARY
++ OP_VLVG uint32 = 0xE722 // VRS-b VECTOR LOAD VR ELEMENT FROM GR
++ OP_VLVGP uint32 = 0xE762 // VRR-f VECTOR LOAD VR FROM GRS DISJOINT
++ OP_VLL uint32 = 0xE737 // VRS-b VECTOR LOAD WITH LENGTH
++ OP_VMX uint32 = 0xE7FF // VRR-c VECTOR MAXIMUM
++ OP_VMXL uint32 = 0xE7FD // VRR-c VECTOR MAXIMUM LOGICAL
++ OP_VMRH uint32 = 0xE761 // VRR-c VECTOR MERGE HIGH
++ OP_VMRL uint32 = 0xE760 // VRR-c VECTOR MERGE LOW
++ OP_VMN uint32 = 0xE7FE // VRR-c VECTOR MINIMUM
++ OP_VMNL uint32 = 0xE7FC // VRR-c VECTOR MINIMUM LOGICAL
++ OP_VMAE uint32 = 0xE7AE // VRR-d VECTOR MULTIPLY AND ADD EVEN
++ OP_VMAH uint32 = 0xE7AB // VRR-d VECTOR MULTIPLY AND ADD HIGH
++ OP_VMALE uint32 = 0xE7AC // VRR-d VECTOR MULTIPLY AND ADD LOGICAL EVEN
++ OP_VMALH uint32 = 0xE7A9 // VRR-d VECTOR MULTIPLY AND ADD LOGICAL HIGH
++ OP_VMALO uint32 = 0xE7AD // VRR-d VECTOR MULTIPLY AND ADD LOGICAL ODD
++ OP_VMAL uint32 = 0xE7AA // VRR-d VECTOR MULTIPLY AND ADD LOW
++ OP_VMAO uint32 = 0xE7AF // VRR-d VECTOR MULTIPLY AND ADD ODD
++ OP_VME uint32 = 0xE7A6 // VRR-c VECTOR MULTIPLY EVEN
++ OP_VMH uint32 = 0xE7A3 // VRR-c VECTOR MULTIPLY HIGH
++ OP_VMLE uint32 = 0xE7A4 // VRR-c VECTOR MULTIPLY EVEN LOGICAL
++ OP_VMLH uint32 = 0xE7A1 // VRR-c VECTOR MULTIPLY HIGH LOGICAL
++ OP_VMLO uint32 = 0xE7A5 // VRR-c VECTOR MULTIPLY ODD LOGICAL
++ OP_VML uint32 = 0xE7A2 // VRR-c VECTOR MULTIPLY LOW
++ OP_VMO uint32 = 0xE7A7 // VRR-c VECTOR MULTIPLY ODD
++ OP_VNO uint32 = 0xE76B // VRR-c VECTOR NOR
++ OP_VO uint32 = 0xE76A // VRR-c VECTOR OR
++ OP_VPK uint32 = 0xE794 // VRR-c VECTOR PACK
++ OP_VPKLS uint32 = 0xE795 // VRR-b VECTOR PACK LOGICAL SATURATE
++ OP_VPKS uint32 = 0xE797 // VRR-b VECTOR PACK SATURATE
++ OP_VPERM uint32 = 0xE78C // VRR-e VECTOR PERMUTE
++ OP_VPDI uint32 = 0xE784 // VRR-c VECTOR PERMUTE DOUBLEWORD IMMEDIATE
++ OP_VPOPCT uint32 = 0xE750 // VRR-a VECTOR POPULATION COUNT
++ OP_VREP uint32 = 0xE74D // VRI-c VECTOR REPLICATE
++ OP_VREPI uint32 = 0xE745 // VRI-a VECTOR REPLICATE IMMEDIATE
++ OP_VSCEF uint32 = 0xE71B // VRV VECTOR SCATTER ELEMENT (32)
++ OP_VSCEG uint32 = 0xE71A // VRV VECTOR SCATTER ELEMENT (64)
++ OP_VSEL uint32 = 0xE78D // VRR-e VECTOR SELECT
++ OP_VSL uint32 = 0xE774 // VRR-c VECTOR SHIFT LEFT
++ OP_VSLB uint32 = 0xE775 // VRR-c VECTOR SHIFT LEFT BY BYTE
++ OP_VSLDB uint32 = 0xE777 // VRI-d VECTOR SHIFT LEFT DOUBLE BY BYTE
++ OP_VSRA uint32 = 0xE77E // VRR-c VECTOR SHIFT RIGHT ARITHMETIC
++ OP_VSRAB uint32 = 0xE77F // VRR-c VECTOR SHIFT RIGHT ARITHMETIC BY BYTE
++ OP_VSRL uint32 = 0xE77C // VRR-c VECTOR SHIFT RIGHT LOGICAL
++ OP_VSRLB uint32 = 0xE77D // VRR-c VECTOR SHIFT RIGHT LOGICAL BY BYTE
++ OP_VSEG uint32 = 0xE75F // VRR-a VECTOR SIGN EXTEND TO DOUBLEWORD
++ OP_VST uint32 = 0xE70E // VRX VECTOR STORE
++ OP_VSTEH uint32 = 0xE709 // VRX VECTOR STORE ELEMENT (16)
++ OP_VSTEF uint32 = 0xE70B // VRX VECTOR STORE ELEMENT (32)
++ OP_VSTEG uint32 = 0xE70A // VRX VECTOR STORE ELEMENT (64)
++ OP_VSTEB uint32 = 0xE708 // VRX VECTOR STORE ELEMENT (8)
++ OP_VSTM uint32 = 0xE73E // VRS-a VECTOR STORE MULTIPLE
++ OP_VSTL uint32 = 0xE73F // VRS-b VECTOR STORE WITH LENGTH
++ OP_VSTRC uint32 = 0xE78A // VRR-d VECTOR STRING RANGE COMPARE
++ OP_VS uint32 = 0xE7F7 // VRR-c VECTOR SUBTRACT
++ OP_VSCBI uint32 = 0xE7F5 // VRR-c VECTOR SUBTRACT COMPUTE BORROW INDICATION
++ OP_VSBCBI uint32 = 0xE7BD // VRR-d VECTOR SUBTRACT WITH BORROW COMPUTE BORROW INDICATION
++ OP_VSBI uint32 = 0xE7BF // VRR-d VECTOR SUBTRACT WITH BORROW INDICATION
++ OP_VSUMG uint32 = 0xE765 // VRR-c VECTOR SUM ACROSS DOUBLEWORD
++ OP_VSUMQ uint32 = 0xE767 // VRR-c VECTOR SUM ACROSS QUADWORD
++ OP_VSUM uint32 = 0xE764 // VRR-c VECTOR SUM ACROSS WORD
++ OP_VTM uint32 = 0xE7D8 // VRR-a VECTOR TEST UNDER MASK
++ OP_VUPH uint32 = 0xE7D7 // VRR-a VECTOR UNPACK HIGH
++ OP_VUPLH uint32 = 0xE7D5 // VRR-a VECTOR UNPACK LOGICAL HIGH
++ OP_VUPLL uint32 = 0xE7D4 // VRR-a VECTOR UNPACK LOGICAL LOW
++ OP_VUPL uint32 = 0xE7D6 // VRR-a VECTOR UNPACK LOW
+)
+
+func oclass(a *obj.Addr) int {
@@ -16334,6 +19662,17 @@ index 0000000..7956f22
+ return rel
+}
+
++func addrilrelocoffset(ctxt *obj.Link, sym *obj.LSym, add, offset int64) *obj.Reloc {
++ offset += int64(2) // relocation offset from start of instruction
++ rel := obj.Addrel(ctxt.Cursym)
++ rel.Off = int32(ctxt.Pc + offset)
++ rel.Siz = 4
++ rel.Sym = sym
++ rel.Add = add + offset + int64(rel.Siz)
++ rel.Type = obj.R_PCRELDBL
++ return rel
++}
++
+// Add a CALL relocation for the immediate in a RIL style instruction.
+// The addend will be adjusted as required.
+func addcallreloc(ctxt *obj.Link, sym *obj.LSym, add int64) *obj.Reloc {
@@ -16601,30 +19940,6 @@ index 0000000..7956f22
+ RXY(a, OP_LAY, uint32(p.To.Reg), uint32(r), 0, uint32(v), asm)
+ }
+
-+ case 4: /* add/mul $scon,[r1],r2 */ //Might have to worry about condition codes
-+ v := regoff(ctxt, &p.From)
-+
-+ r := int(p.To.Reg)
-+ r2 := int(p.Reg)
-+
-+ if p.Reg == 0 && p.To.Reg == 0 {
-+ ctxt.Diag("literal operation on R0\n%v", p)
-+ }
-+ if p.As == AADD {
-+ if r2 == 0 {
-+ RIL(a, OP_AGFI, uint32(r), uint32(v), asm)
-+ } else {
-+ RIE(d, OP_AGHIK, uint32(r), uint32(r2), uint32(v), 0, 0, 0, 0, asm)
-+ }
-+ } else if p.As == AMULLW {
-+ if r2 == 0 {
-+ RIL(a, OP_MSGFI, uint32(r), uint32(v), asm)
-+ } else {
-+ RIL(a, OP_MSGFI, uint32(r2), uint32(v), asm)
-+ RRE(OP_LGFR, uint32(r), uint32(r2), asm)
-+ }
-+ }
-+
+ case 5: /* syscall */ // This might be right, assuming SVC is the same as Power's SC
+ I(OP_SVC, 0, asm)
+
@@ -16921,63 +20236,78 @@ index 0000000..7956f22
+ addrilreloc(ctxt, p.From.Sym, d)
+ }
+
-+ case 20: /* add $ucon,,r */
-+ v := regoff(ctxt, &p.From)
-+
-+ r := int(p.Reg)
-+ if p.As == AADD && p.To.Reg == 0 {
-+ ctxt.Diag("literal operation on R0\n%v", p)
-+ }
-+ if r == 0 {
-+ RIL(a, OP_AGFI, uint32(p.To.Reg), uint32(v), asm)
-+ } else {
-+ RIL(a, OP_LGFI, REGTMP, uint32(v), asm)
-+ RRE(OP_AGR, REGTMP, uint32(r), asm)
-+ RRE(OP_LGR, uint32(p.To.Reg), REGTMP, asm)
-+ }
-+
+ case 22: /* add $lcon,r1,r2 ==> cau+or+add */ /* could do add/sub more efficiently */
+
+ if p.From.Sym != nil {
+ ctxt.Diag("%v is not supported", p)
+ }
+
-+ d := vregoff(ctxt, &p.From)
-+ var opcode uint32
++ v := vregoff(ctxt, &p.From)
++ r := p.Reg
++ if r == 0 {
++ r = p.To.Reg
++ }
+ switch p.As {
+ default:
+ case AADD:
-+ opcode = OP_AGFI
++ if r == p.To.Reg {
++ RIL(a, OP_AGFI, uint32(p.To.Reg), uint32(v), asm)
++ } else if int64(int16(v)) == v {
++ RIE(d, OP_AGHIK, uint32(p.To.Reg), uint32(r), uint32(v), 0, 0, 0, 0, asm)
++ } else {
++ RRE(OP_LGR, uint32(p.To.Reg), uint32(r), asm)
++ RIL(a, OP_AGFI, uint32(p.To.Reg), uint32(v), asm)
++ }
+ case AADDC:
-+ opcode = OP_ALGFI
++ if r != p.To.Reg {
++ RRE(OP_LGR, uint32(p.To.Reg), uint32(r), asm)
++ }
++ RIL(a, OP_ALGFI, uint32(p.To.Reg), uint32(v), asm)
+ case AMULLW:
-+ opcode = OP_MSGFI
-+ }
-+
-+ r := int(p.Reg)
-+ if r != 0 {
-+ RRE(OP_LGR, uint32(p.To.Reg), uint32(r), asm)
++ if r != p.To.Reg {
++ RRE(OP_LGR, uint32(p.To.Reg), uint32(r), asm)
++ }
++ RIL(a, OP_MSGFI, uint32(p.To.Reg), uint32(v), asm)
+ }
-+ RIL(a, opcode, uint32(p.To.Reg), uint32(d), asm)
+
+ case 23: /* and $lcon,r1,r2 ==> cau+or+and */ /* masks could be done using rlnm etc. */
+
-+ d := regoff(ctxt, &p.From)
++ v := vregoff(ctxt, &p.From)
+ var opcode uint32
-+ r := int(p.Reg)
++ r := p.Reg
+ if r == 0 {
++ r = p.To.Reg
++ }
++ if r == p.To.Reg {
+ switch p.As {
+ default:
+ ctxt.Diag("%v is not supported", p)
+ case AAND:
-+ opcode = OP_NGR
++ if v >= 0 { // needs zero extend
++ RIL(a, OP_LGFI, REGTMP, uint32(v), asm)
++ RRE(OP_NGR, uint32(p.To.Reg), REGTMP, asm)
++ } else if int64(int16(v)) == v {
++ RI(OP_NILL, uint32(p.To.Reg), uint32(v), asm)
++ } else { // r.To.Reg & 0xffffffff00000000 & uint32(v)
++ RIL(a, OP_NILF, uint32(p.To.Reg), uint32(v), asm)
++ }
+ case AOR:
-+ opcode = OP_OGR
++ if int64(uint32(v)) != v { // needs sign extend
++ RIL(a, OP_LGFI, REGTMP, uint32(v), asm)
++ RRE(OP_OGR, uint32(p.To.Reg), REGTMP, asm)
++ } else if int64(uint16(v)) == v {
++ RI(OP_OILL, uint32(p.To.Reg), uint32(v), asm)
++ } else {
++ RIL(a, OP_OILF, uint32(p.To.Reg), uint32(v), asm)
++ }
+ case AXOR:
-+ opcode = OP_XGR
++ if int64(uint32(v)) != v { // needs sign extend
++ RIL(a, OP_LGFI, REGTMP, uint32(v), asm)
++ RRE(OP_XGR, uint32(p.To.Reg), REGTMP, asm)
++ } else {
++ RIL(a, OP_XILF, uint32(p.To.Reg), uint32(v), asm)
++ }
+ }
-+ RIL(a, OP_LGFI, REGTMP, uint32(d), asm)
-+ RRE(opcode, uint32(p.To.Reg), REGTMP, asm)
+ } else {
+ switch p.As {
+ default:
@@ -16989,7 +20319,7 @@ index 0000000..7956f22
+ case AXOR:
+ opcode = OP_XGRK
+ }
-+ RIL(a, OP_LGFI, REGTMP, uint32(d), asm)
++ RIL(a, OP_LGFI, REGTMP, uint32(v), asm)
+ RRF(opcode, uint32(r), 0, uint32(p.To.Reg), REGTMP, asm)
+ }
+
@@ -17166,7 +20496,7 @@ index 0000000..7956f22
+ opcode = OP_LNDBR
+ case AFNEG:
+ opcode = OP_LCDFR
-+ case AFRSP:
++ case ALEDBR:
+ opcode = OP_LEDBR
+ case ALDEBR:
+ opcode = OP_LDEBR
@@ -17400,66 +20730,6 @@ index 0000000..7956f22
+ RSY(OP_SRLK, uint32(p.To.Reg), uint32(r), 0, uint32(v), asm)
+ }
+
-+ case 58: /* logical $andcon,[s],a */
-+ d := regoff(ctxt, &p.From)
-+
-+ switch p.As {
-+ case AAND, AOR, AXOR:
-+ var opcode1, opcode2 uint32
-+ switch p.As {
-+ default:
-+ ctxt.Diag("%v is not supported", p)
-+ case AAND:
-+ opcode1 = OP_NGR
-+ opcode2 = OP_NGRK
-+ case AOR:
-+ opcode1 = OP_OGR
-+ opcode2 = OP_OGRK
-+ case AXOR:
-+ opcode1 = OP_XGR
-+ opcode2 = OP_XGRK
-+ }
-+
-+ r := int(p.Reg)
-+ if r == 0 {
-+ RIL(a, OP_LGFI, REGTMP, uint32(d), asm)
-+ RRE(opcode1, uint32(p.To.Reg), REGTMP, asm)
-+ } else {
-+ RIL(a, OP_LGFI, REGTMP, uint32(d), asm)
-+ RRF(opcode2, uint32(r), 0, uint32(p.To.Reg), REGTMP, asm)
-+ }
-+ }
-+
-+ case 59: /* or/and $ucon,,r */
-+ d := regoff(ctxt, &p.From)
-+
-+ switch p.As {
-+ case AAND, AOR, AXOR:
-+ var opcode1, opcode2 uint32
-+ switch p.As {
-+ default:
-+ ctxt.Diag("%v is not supported", p)
-+ case AAND:
-+ opcode1 = OP_NGR
-+ opcode2 = OP_NGRK
-+ case AOR:
-+ opcode1 = OP_OGR
-+ opcode2 = OP_OGRK
-+ case AXOR:
-+ opcode1 = OP_XGR
-+ opcode2 = OP_XGRK
-+ }
-+
-+ r := int(p.Reg)
-+ if r == 0 {
-+ RIL(a, OP_LGFI, REGTMP, uint32(d), asm)
-+ RRE(opcode1, uint32(p.To.Reg), REGTMP, asm)
-+ } else {
-+ RIL(a, OP_LGFI, REGTMP, uint32(d), asm)
-+ RRF(opcode2, uint32(r), 0, uint32(p.To.Reg), REGTMP, asm)
-+ }
-+ }
-+
+ case 62: /* rlwmi $sh,s,$mask,a */
+ v := regoff(ctxt, &p.From)
+ d := vregoff(ctxt, p.From3)
@@ -17547,6 +20817,101 @@ index 0000000..7956f22
+ }
+ RIL(0, uint32(zopril(ctxt, int(p.As))), uint32(p.From.Reg), uint32(int32(regoff(ctxt, &p.To))), asm)
+
++ case 72: // MOV int32 -> s+o(r)(i*1)
++ v := regoff(ctxt, &p.From)
++ d := regoff(ctxt, &p.To)
++ r := p.To.Reg
++ x := p.To.Index
++ if r == 0 {
++ r = o.param
++ }
++ if p.From.Sym != nil {
++ RIL(b, OP_LARL, REGTMP, 0, asm)
++ if v&0x1 != 0 {
++ v -= 1
++ RX(OP_LA, uint32(REGTMP), uint32(REGTMP), 0, 1, asm)
++ }
++ addrilreloc(ctxt, p.From.Sym, int64(v))
++ if d < -DISP20/2 || d >= DISP20/2 {
++ RIL(a, OP_LGFI, REGTMP2, uint32(d), asm)
++ if x != 0 {
++ RRE(OP_AGR, REGTMP2, uint32(x), asm)
++ }
++ d = 0
++ x = REGTMP2
++ }
++ RXY(0, zopstore(ctxt, int(p.As)), REGTMP, uint32(x), uint32(r), uint32(d), asm)
++ } else if int32(int16(v)) == v && x == 0 && d >= 0 && d < DISP12 {
++ var opcode uint32
++ switch p.As {
++ case AMOVD:
++ opcode = OP_MVGHI
++ case AMOVW, AMOVWZ:
++ opcode = OP_MVHI
++ case AMOVH, AMOVHZ:
++ opcode = OP_MVHHI
++ case AMOVB, AMOVBZ:
++ opcode = OP_MVI
++ }
++ if opcode == OP_MVI {
++ SI(opcode, uint32(v), uint32(r), uint32(d), asm)
++ } else {
++ SIL(opcode, uint32(r), uint32(d), uint32(v), asm)
++ }
++ } else {
++ RIL(a, OP_LGFI, REGTMP, uint32(v), asm)
++ if d < -DISP20/2 || d >= DISP20/2 {
++ RIL(a, OP_LGFI, REGTMP2, uint32(d), asm)
++ if x != 0 {
++ RRE(OP_AGR, REGTMP2, uint32(x), asm)
++ }
++ d = 0
++ x = REGTMP2
++ }
++ RXY(0, zopstore(ctxt, int(p.As)), REGTMP, uint32(x), uint32(r), uint32(d), asm)
++ }
++
++ case 73: // MOV int32 -> addr
++ v := regoff(ctxt, &p.From)
++ d := regoff(ctxt, &p.To)
++ a := uint32(0)
++ if d&1 != 0 {
++ d -= 1
++ a = 1
++ }
++ RIL(b, OP_LARL, REGTMP, uint32(d), asm)
++ addrilreloc(ctxt, p.To.Sym, int64(d))
++ if p.From.Sym != nil {
++ RIL(b, OP_LARL, REGTMP2, 0, asm)
++ a := uint32(0)
++ if v&0x1 != 0 {
++ v -= 1
++ RX(OP_LA, uint32(REGTMP2), uint32(REGTMP2), 0, 1, asm)
++ }
++ addrilrelocoffset(ctxt, p.From.Sym, int64(v), FORMAT_RIL_size)
++ RXY(0, zopstore(ctxt, int(p.As)), REGTMP2, 0, REGTMP, a, asm)
++ } else if int32(int16(v)) == v {
++ var opcode uint32
++ switch p.As {
++ case AMOVD:
++ opcode = OP_MVGHI
++ case AMOVW, AMOVWZ:
++ opcode = OP_MVHI
++ case AMOVH, AMOVHZ:
++ opcode = OP_MVHHI
++ case AMOVB, AMOVBZ:
++ opcode = OP_MVI
++ }
++ if opcode == OP_MVI {
++ SI(opcode, uint32(v), uint32(REGTMP), a, asm)
++ } else {
++ SIL(opcode, uint32(REGTMP), a, uint32(v), asm)
++ }
++ } else {
++ RIL(a, OP_LGFI, REGTMP2, uint32(v), asm)
++ RXY(0, zopstore(ctxt, int(p.As)), REGTMP2, 0, REGTMP, a, asm)
++ }
++
+ /* relocation operations */
+ case 74: /* AMOV[F][D|W|H|B|S][Z] Rs, addr -> ST[G|H]RL Rs, addr (with a reloaction entry ) */
+ v := regoff(ctxt, &p.To)
@@ -17714,11 +21079,13 @@ index 0000000..7956f22
+
+ case 84: /* storage-and-storage operations (mvc, clc, xc, oc, nc) */
+ l := regoff(ctxt, p.From3)
-+ d2 := regoff(ctxt, &p.From)
+ d1 := regoff(ctxt, &p.To)
++ d2 := regoff(ctxt, &p.From)
+ if l < 1 || l > 256 {
+ ctxt.Diag("number of bytes (%v) not in range [1,256]", l)
+ }
++ b1 := p.To.Reg
++ b2 := p.From.Reg
+ var opcode uint32
+ switch p.As {
+ default:
@@ -17727,6 +21094,9 @@ index 0000000..7956f22
+ opcode = OP_MVC
+ case ACLC:
+ opcode = OP_CLC
++ // swap operand order for CLC so that it matches CMP
++ b1, b2 = b2, b1
++ d1, d2 = d2, d1
+ case AXC:
+ opcode = OP_XC
+ case AOC:
@@ -17734,7 +21104,7 @@ index 0000000..7956f22
+ case ANC:
+ opcode = OP_NC
+ }
-+ SS(a, opcode, uint32(l-1), 0, uint32(p.To.Reg), uint32(d1), uint32(p.From.Reg), uint32(d2), asm)
++ SS(a, opcode, uint32(l-1), 0, uint32(b1), uint32(d1), uint32(b2), uint32(d2), asm)
+
+ case 85: /* larl: load address relative long */
+ // When using larl directly, don't add a nop
@@ -17750,12 +21120,17 @@ index 0000000..7956f22
+ RIL(b, OP_LARL, uint32(p.To.Reg), uint32(v>>1), asm)
+
+ case 86: /* lay?: load address */
-+ v := vregoff(ctxt, &p.From)
++ d := vregoff(ctxt, &p.From)
++ x := p.From.Index
++ b := p.From.Reg
++ if b == 0 {
++ b = o.param
++ }
+ switch p.As {
+ case ALA:
-+ RX(OP_LA, uint32(p.To.Reg), uint32(p.From.Reg), 0, uint32(v), asm)
++ RX(OP_LA, uint32(p.To.Reg), uint32(x), uint32(b), uint32(d), asm)
+ case ALAY:
-+ RXY(0, OP_LAY, uint32(p.To.Reg), uint32(p.From.Reg), 0, uint32(v), asm)
++ RXY(0, OP_LAY, uint32(p.To.Reg), uint32(x), uint32(b), uint32(d), asm)
+ }
+
+ case 87: /* exrl: execute relative long */
@@ -17790,11 +21165,10 @@ index 0000000..7956f22
+ S(opcode, uint32(r), uint32(v), asm)
+
+ case 89:
-+ if p.Pcond == nil {
-+ ctxt.Diag("no branch target")
-+ break
++ var v int32
++ if p.Pcond != nil {
++ v = int32((p.Pcond.Pc - p.Pc) >> 1)
+ }
-+ v := int32((p.Pcond.Pc - p.Pc) >> 1)
+ var opcode, opcode2 uint32
+ switch p.As {
+ case ACMPBEQ, ACMPBGE, ACMPBGT, ACMPBLE, ACMPBLT, ACMPBNE:
@@ -17813,9 +21187,9 @@ index 0000000..7956f22
+ }
+
+ case 90:
-+ if p.Pcond == nil {
-+ ctxt.Diag("no branch target")
-+ break
++ var v int32
++ if p.Pcond != nil {
++ v = int32((p.Pcond.Pc - p.Pc) >> 1)
+ }
+ var opcode, opcode2 uint32
+ switch p.As {
@@ -17826,7 +21200,6 @@ index 0000000..7956f22
+ opcode = OP_CLGIJ
+ opcode2 = OP_CLGFI
+ }
-+ v := int32((p.Pcond.Pc - p.Pc) >> 1)
+ mask := branchMask(ctxt, p)
+ if int32(int16(v)) != v {
+ RIL(0, opcode2, uint32(p.From.Reg), uint32(int32(regoff(ctxt, p.From3))), asm)
@@ -17835,26 +21208,6 @@ index 0000000..7956f22
+ RIE(c, opcode, uint32(p.From.Reg), mask, uint32(v), 0, 0, 0, uint32(int32(regoff(ctxt, p.From3))), asm)
+ }
+
-+ case 92:
-+ var opcode uint32
-+ switch p.As {
-+ case AMOVD:
-+ opcode = OP_MVGHI
-+ case AMOVW, AMOVWZ:
-+ opcode = OP_MVHI
-+ case AMOVH, AMOVHZ:
-+ opcode = OP_MVHHI
-+ case AMOVB, AMOVBZ:
-+ opcode = OP_MVI
-+ }
-+ v := regoff(ctxt, &p.From)
-+ d := regoff(ctxt, &p.To)
-+ if opcode == OP_MVI {
-+ SI(opcode, uint32(v), uint32(p.To.Reg), uint32(d), asm)
-+ } else {
-+ SIL(opcode, uint32(p.To.Reg), uint32(d), uint32(v), asm)
-+ }
-+
+ case 93: // GOT lookup
+ v := vregoff(ctxt, &p.To)
+ if v != 0 {
@@ -17904,8 +21257,291 @@ index 0000000..7956f22
+ RXY(0, OP_LGF, uint32(p.To.Reg), REGTMP, 0, 0, asm)
+ // TODO(mundaym): add R_390_TLS_LOAD relocation here
+ // not strictly required but might allow the linker to optimize
-+ }
-+}
++
++ case 96: // CLEAR macro
++ length := vregoff(ctxt, &p.From)
++ offset := vregoff(ctxt, &p.To)
++ reg := p.To.Reg
++ if reg == 0 {
++ reg = o.param
++ }
++ if length <= 0 {
++ ctxt.Diag("cannot CLEAR %d bytes, must be greater than 0", length)
++ }
++ for length > 0 {
++ if offset < 0 || offset >= DISP12 {
++ if offset >= -DISP20/2 && offset < DISP20/2 {
++ RXY(0, OP_LAY, uint32(REGTMP), uint32(reg), 0, uint32(offset), asm)
++ } else {
++ if reg != REGTMP {
++ RRE(OP_LGR, uint32(REGTMP), uint32(reg), asm)
++ }
++ RIL(a, OP_AGFI, uint32(REGTMP), uint32(offset), asm)
++ }
++ reg = REGTMP
++ offset = 0
++ }
++ size := length
++ if size > 256 {
++ size = 256
++ }
++
++ switch size {
++ case 1:
++ SI(OP_MVI, 0, uint32(reg), uint32(offset), asm)
++ case 2:
++ SIL(OP_MVHHI, uint32(reg), uint32(offset), 0, asm)
++ case 4:
++ SIL(OP_MVHI, uint32(reg), uint32(offset), 0, asm)
++ case 8:
++ SIL(OP_MVGHI, uint32(reg), uint32(offset), 0, asm)
++ default:
++ SS(a, OP_XC, uint32(size-1), 0, uint32(reg), uint32(offset), uint32(reg), uint32(offset), asm)
++ }
++
++ length -= size
++ offset += size
++ }
++
++ case 97: // STORE MULTIPLE (STMG/STMY)
++ rstart := p.From.Reg
++ rend := p.Reg
++ offset := vregoff(ctxt, &p.To)
++ reg := p.To.Reg
++ if reg == 0 {
++ reg = o.param
++ }
++ if offset < -DISP20/2 || offset >= DISP20/2 {
++ if reg != REGTMP {
++ RRE(OP_LGR, uint32(REGTMP), uint32(reg), asm)
++ }
++ RIL(a, OP_AGFI, uint32(REGTMP), uint32(offset), asm)
++ reg = REGTMP
++ }
++ switch p.As {
++ case ASTMY:
++ if offset >= 0 && offset < DISP12 {
++ RS(OP_STM, uint32(rstart), uint32(rend), uint32(reg), uint32(offset), asm)
++ } else {
++ RSY(OP_STMY, uint32(rstart), uint32(rend), uint32(reg), uint32(offset), asm)
++ }
++ case ASTMG:
++ RSY(OP_STMG, uint32(rstart), uint32(rend), uint32(reg), uint32(offset), asm)
++ }
++
++ case 98: // LOAD MULTIPLE (LMG/LMY)
++ rstart := p.Reg
++ rend := p.To.Reg
++ offset := vregoff(ctxt, &p.From)
++ reg := p.From.Reg
++ if reg == 0 {
++ reg = o.param
++ }
++ if offset < -DISP20/2 || offset >= DISP20/2 {
++ if reg != REGTMP {
++ RRE(OP_LGR, uint32(REGTMP), uint32(reg), asm)
++ }
++ RIL(a, OP_AGFI, uint32(REGTMP), uint32(offset), asm)
++ reg = REGTMP
++ }
++ switch p.As {
++ case ALMY:
++ if offset >= 0 && offset < DISP12 {
++ RS(OP_LM, uint32(rstart), uint32(rend), uint32(reg), uint32(offset), asm)
++ } else {
++ RSY(OP_LMY, uint32(rstart), uint32(rend), uint32(reg), uint32(offset), asm)
++ }
++ case ALMG:
++ RSY(OP_LMG, uint32(rstart), uint32(rend), uint32(reg), uint32(offset), asm)
++ }
++
++ case 100: // VRX STORE
++ op, m3, _ := vop(p.As)
++ if p.From3 != nil {
++ m3 = uint32(vregoff(ctxt, p.From3))
++ }
++ b2 := p.To.Reg
++ if b2 == 0 {
++ b2 = o.param
++ }
++ d2 := uint32(vregoff(ctxt, &p.To))
++ vrx(op, uint32(p.From.Reg), uint32(p.To.Index), uint32(b2), d2, m3, asm)
++
++ case 101: // VRX LOAD
++ op, m3, _ := vop(p.As)
++ if p.From3 != nil {
++ m3 = uint32(vregoff(ctxt, p.From3))
++ }
++ b2 := p.From.Reg
++ if b2 == 0 {
++ b2 = o.param
++ }
++ d2 := uint32(vregoff(ctxt, &p.From))
++ vrx(op, uint32(p.To.Reg), uint32(p.From.Index), uint32(b2), d2, m3, asm)
++
++ case 102: // VRV SCATTER
++ op, m3, _ := vop(p.As)
++ if p.From3 != nil {
++ m3 = uint32(vregoff(ctxt, p.From3))
++ }
++ b2 := p.To.Reg
++ if b2 == 0 {
++ b2 = o.param
++ }
++ d2 := uint32(vregoff(ctxt, &p.To))
++ vrv(op, uint32(p.From.Reg), uint32(p.To.Index), uint32(b2), d2, m3, asm)
++
++ case 103: // VRV GATHER
++ op, m3, _ := vop(p.As)
++ if p.From3 != nil {
++ m3 = uint32(vregoff(ctxt, p.From3))
++ }
++ b2 := p.From.Reg
++ if b2 == 0 {
++ b2 = o.param
++ }
++ d2 := uint32(vregoff(ctxt, &p.From))
++ vrv(op, uint32(p.To.Reg), uint32(p.From.Index), uint32(b2), d2, m3, asm)
++
++ case 104: // VRS SHIFT/ROTATE and LOAD GR FROM VR ELEMENT
++ op, m4, _ := vop(p.As)
++ fr := p.Reg
++ if fr == 0 {
++ fr = p.To.Reg
++ }
++ bits := uint32(vregoff(ctxt, &p.From))
++ vrs(op, uint32(p.To.Reg), uint32(fr), uint32(p.From.Reg), bits, m4, asm)
++
++ case 105: // VRS STORE MULTIPLE
++ op, _, _ := vop(p.As)
++ offset := uint32(vregoff(ctxt, &p.To))
++ reg := p.To.Reg
++ if reg == 0 {
++ reg = o.param
++ }
++ vrs(op, uint32(p.From.Reg), uint32(p.Reg), uint32(reg), offset, 0, asm)
++
++ case 106: // VRS LOAD MULTIPLE
++ op, _, _ := vop(p.As)
++ offset := uint32(vregoff(ctxt, &p.From))
++ reg := p.From.Reg
++ if reg == 0 {
++ reg = o.param
++ }
++ vrs(op, uint32(p.Reg), uint32(p.To.Reg), uint32(reg), offset, 0, asm)
++
++ case 107: // VRS STORE WITH LENGTH
++ op, _, _ := vop(p.As)
++ offset := uint32(vregoff(ctxt, &p.To))
++ reg := p.To.Reg
++ if reg == 0 {
++ reg = o.param
++ }
++ vrs(op, uint32(p.From.Reg), uint32(p.From3.Reg), uint32(reg), offset, 0, asm)
++
++ case 108: // VRS LOAD WITH LENGTH
++ op, _, _ := vop(p.As)
++ offset := uint32(vregoff(ctxt, &p.From))
++ reg := p.From.Reg
++ if reg == 0 {
++ reg = o.param
++ }
++ vrs(op, uint32(p.To.Reg), uint32(p.From3.Reg), uint32(reg), offset, 0, asm)
++
++ case 109: // VRI-a instructions
++ op, _, _ := vop(p.As)
++ i2 := uint32(vregoff(ctxt, &p.From))
++ switch p.As {
++ case AVZERO:
++ i2 = 0
++ case AVONE:
++ i2 = 0xffff
++ }
++ m3 := uint32(0)
++ if p.From3 != nil {
++ m3 = uint32(vregoff(ctxt, p.From3))
++ }
++ vria(op, uint32(p.To.Reg), i2, m3, asm)
++
++ case 110:
++ op, m4, _ := vop(p.As)
++ i2 := uint32(vregoff(ctxt, p.From3))
++ i3 := uint32(vregoff(ctxt, &p.From))
++ vrib(op, uint32(p.To.Reg), i2, i3, m4, asm)
++
++ case 111:
++ op, m4, _ := vop(p.As)
++ i2 := uint32(vregoff(ctxt, &p.From))
++ vric(op, uint32(p.To.Reg), uint32(p.Reg), i2, m4, asm)
++
++ case 112:
++ op, m5, _ := vop(p.As)
++ i4 := uint32(vregoff(ctxt, p.From3))
++ vrid(op, uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg), i4, m5, asm)
++
++ case 113:
++ op, m4, _ := vop(p.As)
++ m5 := singleElementMask(p.As)
++ i3 := uint32(vregoff(ctxt, &p.From))
++ vrie(op, uint32(p.To.Reg), uint32(p.Reg), i3, m5, m4, asm)
++
++ case 114: // VRR-a
++ op, m3, m5 := vop(p.As)
++ m4 := singleElementMask(p.As)
++ vrra(op, uint32(p.To.Reg), uint32(p.From.Reg), m5, m4, m3, asm)
++
++ case 115: // VRR-a COMPARE
++ op, m3, m5 := vop(p.As)
++ m4 := singleElementMask(p.As)
++ vrra(op, uint32(p.From.Reg), uint32(p.To.Reg), m5, m4, m3, asm)
++
++ case 116: // VRR-a
++
++ case 117: // VRR-b
++ op, m4, m5 := vop(p.As)
++ vrrb(op, uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg), m5, m4, asm)
++
++ case 118: // VRR-c
++ op, m4, m6 := vop(p.As)
++ m5 := singleElementMask(p.As)
++ v3 := p.Reg
++ if v3 == 0 {
++ v3 = p.To.Reg
++ }
++ vrrc(op, uint32(p.To.Reg), uint32(p.From.Reg), uint32(v3), m6, m5, m4, asm)
++
++ case 119: // VRR-c SHIFT/ROTATE/DIVIDE/SUB (rhs value on the left, like SLD, DIV etc.)
++ op, m4, m6 := vop(p.As)
++ m5 := singleElementMask(p.As)
++ v2 := p.Reg
++ if v2 == 0 {
++ v2 = p.To.Reg
++ }
++ vrrc(op, uint32(p.To.Reg), uint32(v2), uint32(p.From.Reg), m6, m5, m4, asm)
++
++ case 120: // VRR-d
++ op, m6, _ := vop(p.As)
++ m5 := singleElementMask(p.As)
++ v1 := uint32(p.To.Reg)
++ v2 := uint32(p.From3.Reg)
++ v3 := uint32(p.From.Reg)
++ v4 := uint32(p.Reg)
++ vrrd(op, v1, v2, v3, m6, m5, v4, asm)
++
++ case 121: // VRR-e
++ op, m6, _ := vop(p.As)
++ m5 := singleElementMask(p.As)
++ v1 := uint32(p.To.Reg)
++ v2 := uint32(p.From3.Reg)
++ v3 := uint32(p.From.Reg)
++ v4 := uint32(p.Reg)
++ vrre(op, v1, v2, v3, m5, m6, v4, asm)
++
++ case 122: // VRR-f LOAD VRS FROM GRS DISJOINT
++ op, _, _ := vop(p.As)
++ vrrf(op, uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg), asm)
++ }
++}
+
+func vregoff(ctxt *obj.Link, a *obj.Addr) int64 {
+ ctxt.Instoffset = 0
@@ -18397,12 +22033,169 @@ index 0000000..7956f22
+ (uint8(b2)<<4)|uint8((d2>>8)&0x0F),
+ uint8(d2))
+}
++
++func rxb(va, vb, vc, vd uint32) uint8 {
++ mask := uint8(0)
++ if va >= REG_V16 && va <= REG_V31 {
++ mask |= 0x8
++ }
++ if vb >= REG_V16 && vb <= REG_V31 {
++ mask |= 0x4
++ }
++ if vc >= REG_V16 && vc <= REG_V31 {
++ mask |= 0x2
++ }
++ if vd >= REG_V16 && vd <= REG_V31 {
++ mask |= 0x1
++ }
++ return mask
++}
++
++func vrx(op, v1, x2, b2, d2, m3 uint32, asm *[]byte) {
++ *asm = append(*asm,
++ uint8(op>>8),
++ (uint8(v1)<<4)|(uint8(x2)&0xf),
++ (uint8(b2)<<4)|(uint8(d2>>8)&0xf),
++ uint8(d2),
++ (uint8(m3)<<4)|rxb(v1, 0, 0, 0),
++ uint8(op))
++}
++
++func vrv(op, v1, v2, b2, d2, m3 uint32, asm *[]byte) {
++ *asm = append(*asm,
++ uint8(op>>8),
++ (uint8(v1)<<4)|(uint8(v2)&0xf),
++ (uint8(b2)<<4)|(uint8(d2>>8)&0xf),
++ uint8(d2),
++ (uint8(m3)<<4)|rxb(v1, v2, 0, 0),
++ uint8(op))
++}
++
++func vrs(op, v1, v3_r3, b2, d2, m4 uint32, asm *[]byte) {
++ *asm = append(*asm,
++ uint8(op>>8),
++ (uint8(v1)<<4)|(uint8(v3_r3)&0xf),
++ (uint8(b2)<<4)|(uint8(d2>>8)&0xf),
++ uint8(d2),
++ (uint8(m4)<<4)|rxb(v1, v3_r3, 0, 0),
++ uint8(op))
++}
++
++func vrra(op, v1, v2, m5, m4, m3 uint32, asm *[]byte) {
++ *asm = append(*asm,
++ uint8(op>>8),
++ (uint8(v1)<<4)|(uint8(v2)&0xf),
++ 0,
++ (uint8(m5)<<4)|(uint8(m4)&0xf),
++ (uint8(m3)<<4)|rxb(v1, v2, 0, 0),
++ uint8(op))
++}
++
++func vrrb(op, v1, v2, v3, m5, m4 uint32, asm *[]byte) {
++ *asm = append(*asm,
++ uint8(op>>8),
++ (uint8(v1)<<4)|(uint8(v2)&0xf),
++ uint8(v3)<<4,
++ uint8(m5)<<4,
++ (uint8(m4)<<4)|rxb(v1, v2, v3, 0),
++ uint8(op))
++}
++
++func vrrc(op, v1, v2, v3, m6, m5, m4 uint32, asm *[]byte) {
++ *asm = append(*asm,
++ uint8(op>>8),
++ (uint8(v1)<<4)|(uint8(v2)&0xf),
++ uint8(v3)<<4,
++ (uint8(m6)<<4)|(uint8(m5)&0xf),
++ (uint8(m4)<<4)|rxb(v1, v2, v3, 0),
++ uint8(op))
++}
++
++func vrrd(op, v1, v2, v3, m5, m6, v4 uint32, asm *[]byte) {
++ *asm = append(*asm,
++ uint8(op>>8),
++ (uint8(v1)<<4)|(uint8(v2)&0xf),
++ (uint8(v3)<<4)|(uint8(m5)&0xf),
++ uint8(m6)<<4,
++ (uint8(v4)<<4)|rxb(v1, v2, v3, v4),
++ uint8(op))
++}
++
++func vrre(op, v1, v2, v3, m6, m5, v4 uint32, asm *[]byte) {
++ *asm = append(*asm,
++ uint8(op>>8),
++ (uint8(v1)<<4)|(uint8(v2)&0xf),
++ (uint8(v3)<<4)|(uint8(m6)&0xf),
++ uint8(m5),
++ (uint8(v4)<<4)|rxb(v1, v2, v3, v4),
++ uint8(op))
++}
++
++func vrrf(op, v1, r2, r3 uint32, asm *[]byte) {
++ *asm = append(*asm,
++ uint8(op>>8),
++ (uint8(v1)<<4)|(uint8(r2)&0xf),
++ uint8(r3)<<4,
++ 0,
++ rxb(v1, 0, 0, 0),
++ uint8(op))
++}
++
++func vria(op, v1, i2, m3 uint32, asm *[]byte) {
++ *asm = append(*asm,
++ uint8(op>>8),
++ uint8(v1)<<4,
++ uint8(i2>>8),
++ uint8(i2),
++ (uint8(m3)<<4)|rxb(v1, 0, 0, 0),
++ uint8(op))
++}
++
++func vrib(op, v1, i2, i3, m4 uint32, asm *[]byte) {
++ *asm = append(*asm,
++ uint8(op>>8),
++ uint8(v1)<<4,
++ uint8(i2),
++ uint8(i3),
++ (uint8(m4)<<4)|rxb(v1, 0, 0, 0),
++ uint8(op))
++}
++
++func vric(op, v1, v3, i2, m4 uint32, asm *[]byte) {
++ *asm = append(*asm,
++ uint8(op>>8),
++ (uint8(v1)<<4)|(uint8(v3)&0xf),
++ uint8(i2>>8),
++ uint8(i2),
++ (uint8(m4)<<4)|rxb(v1, v3, 0, 0),
++ uint8(op))
++}
++
++func vrid(op, v1, v2, v3, i4, m5 uint32, asm *[]byte) {
++ *asm = append(*asm,
++ uint8(op>>8),
++ (uint8(v1)<<4)|(uint8(v2)&0xf),
++ uint8(v3)<<4,
++ uint8(i4),
++ (uint8(m5)<<4)|rxb(v1, v2, v3, 0),
++ uint8(op))
++}
++
++func vrie(op, v1, v2, i3, m5, m4 uint32, asm *[]byte) {
++ *asm = append(*asm,
++ uint8(op>>8),
++ (uint8(v1)<<4)|(uint8(v2)&0xf),
++ uint8(i3>>4),
++ (uint8(i3)<<4)|(uint8(m5)&0xf),
++ (uint8(m4)<<4)|rxb(v1, v2, 0, 0),
++ uint8(op))
++}
diff --git a/src/cmd/internal/obj/s390x/listz.go b/src/cmd/internal/obj/s390x/listz.go
new file mode 100644
-index 0000000..c6cb48f
+index 0000000..99702c9
--- /dev/null
+++ b/src/cmd/internal/obj/s390x/listz.go
-@@ -0,0 +1,70 @@
+@@ -0,0 +1,73 @@
+// Based on cmd/internal/obj/ppc64/list9.go.
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
@@ -18461,6 +22254,9 @@ index 0000000..c6cb48f
+ if REG_AR0 <= r && r <= REG_AR15 {
+ return fmt.Sprintf("AR%d", r-REG_AR0)
+ }
++ if REG_V0 <= r && r <= REG_V31 {
++ return fmt.Sprintf("V%d", r-REG_V0)
++ }
+ return fmt.Sprintf("Rgok(%d)", r-obj.RBaseS390X)
+}
+
@@ -18475,10 +22271,10 @@ index 0000000..c6cb48f
+}
diff --git a/src/cmd/internal/obj/s390x/objz.go b/src/cmd/internal/obj/s390x/objz.go
new file mode 100644
-index 0000000..71c6fb5
+index 0000000..1beb068
--- /dev/null
+++ b/src/cmd/internal/obj/s390x/objz.go
-@@ -0,0 +1,990 @@
+@@ -0,0 +1,1014 @@
+// Based on cmd/internal/obj/ppc64/obj9.go.
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
@@ -18756,17 +22552,15 @@ index 0000000..71c6fb5
+ AFDIV,
+ AFMADD,
+ AFMOVD,
-+ /* case AFMOVDS: */
+ AFMOVS,
-+
-+ /* case AFMOVSD: */
+ AFMSUB,
+ AFMUL,
+ AFNABS,
+ AFNEG,
+ AFNMADD,
+ AFNMSUB,
-+ AFRSP,
++ ALEDBR,
++ ALDEBR,
+ AFSUB:
+ q = p
+
@@ -18851,7 +22645,12 @@ index 0000000..71c6fb5
+ var o int
+ var p1 *obj.Prog
+ var p2 *obj.Prog
++ var pLast *obj.Prog
++ var pPre *obj.Prog
++ var pPreempt *obj.Prog
++ wasSplit := false
+ for p := cursym.Text; p != nil; p = p.Link {
++ pLast = p
+ o = int(p.As)
+ switch o {
+ case obj.ATEXT:
@@ -18873,14 +22672,17 @@ index 0000000..71c6fb5
+ q = p
+
+ if p.From3.Offset&obj.NOSPLIT == 0 {
-+ p = stacksplit(ctxt, p, autosize) // emit split check
++ p, pPreempt = stacksplitPre(ctxt, p, autosize) // emit pre part of split check
++ pPre = p
++ wasSplit = true //need post part of split
+ }
+
+ if autosize != 0 {
+ q = obj.Appendp(ctxt, p)
-+ q.As = AADD
-+ q.From.Type = obj.TYPE_CONST
++ q.As = AMOVD
++ q.From.Type = obj.TYPE_ADDR
+ q.From.Offset = int64(-autosize)
++ q.From.Reg = REGSP // not actually needed - REGSP is assumed if no reg is provided
+ q.To.Type = obj.TYPE_REG
+ q.To.Reg = REGSP
+ q.Spadj = autosize
@@ -19072,6 +22874,9 @@ index 0000000..71c6fb5
+ }
+ }
+ }
++ if wasSplit {
++ pLast = stacksplitPost(ctxt, pLast, pPre, pPreempt) // emit post part of split check
++ }
+}
+
+/*
@@ -19119,7 +22924,9 @@ index 0000000..71c6fb5
+ q = p;
+ }
+*/
-+func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32) *obj.Prog {
++func stacksplitPre(ctxt *obj.Link, p *obj.Prog, framesize int32) (*obj.Prog, *obj.Prog) {
++ var q *obj.Prog
++
+ // MOVD g_stackguard(g), R3
+ p = obj.Appendp(ctxt, p)
+
@@ -19133,17 +22940,35 @@ index 0000000..71c6fb5
+ p.To.Type = obj.TYPE_REG
+ p.To.Reg = REG_R3
+
-+ var q *obj.Prog
++ q = nil
+ if framesize <= obj.StackSmall {
+ // small stack: SP < stackguard
+ // CMP stackguard, SP
-+ p = obj.Appendp(ctxt, p)
+
-+ p.As = ACMPU
++ //p.To.Type = obj.TYPE_REG
++ //p.To.Reg = REGSP
++
++ // q1: BLT done
++
++ p = obj.Appendp(ctxt, p)
++ //q1 = p
+ p.From.Type = obj.TYPE_REG
+ p.From.Reg = REG_R3
-+ p.To.Type = obj.TYPE_REG
-+ p.To.Reg = REGSP
++ p.Reg = REGSP
++ p.As = ACMPUBGE
++ p.To.Type = obj.TYPE_BRANCH
++ //p = obj.Appendp(ctxt, p)
++
++ //p.As = ACMPU
++ //p.From.Type = obj.TYPE_REG
++ //p.From.Reg = REG_R3
++ //p.To.Type = obj.TYPE_REG
++ //p.To.Reg = REGSP
++
++ //p = obj.Appendp(ctxt, p)
++ //p.As = ABGE
++ //p.To.Type = obj.TYPE_BRANCH
++
+ } else if framesize <= obj.StackBig {
+ // large stack: SP-framesize < stackguard-StackSmall
+ // ADD $-framesize, SP, R4
@@ -19158,11 +22983,12 @@ index 0000000..71c6fb5
+ p.To.Reg = REG_R4
+
+ p = obj.Appendp(ctxt, p)
-+ p.As = ACMPU
+ p.From.Type = obj.TYPE_REG
+ p.From.Reg = REG_R3
-+ p.To.Type = obj.TYPE_REG
-+ p.To.Reg = REG_R4
++ p.Reg = REG_R4
++ p.As = ACMPUBGE
++ p.To.Type = obj.TYPE_BRANCH
++
+ } else {
+ // Such a large stack we need to protect against wraparound.
+ // If SP is close to zero:
@@ -19177,8 +23003,8 @@ index 0000000..71c6fb5
+ // BEQ label-of-call-to-morestack
+ // ADD $StackGuard, SP, R4
+ // SUB R3, R4
-+ // MOVD $(framesize+(StackGuard-StackSmall)), R31
-+ // CMPU R31, R4
++ // MOVD $(framesize+(StackGuard-StackSmall)), TEMP
++ // CMPUBGE TEMP, R4
+ p = obj.Appendp(ctxt, p)
+
+ p.As = ACMP
@@ -19215,30 +23041,28 @@ index 0000000..71c6fb5
+ p.To.Reg = REGTMP
+
+ p = obj.Appendp(ctxt, p)
-+ p.As = ACMPU
+ p.From.Type = obj.TYPE_REG
+ p.From.Reg = REGTMP
-+ p.To.Type = obj.TYPE_REG
-+ p.To.Reg = REG_R4
++ p.Reg = REG_R4
++ p.As = ACMPUBGE
++ p.To.Type = obj.TYPE_BRANCH
+ }
+
-+ // q1: BLT done
-+ p = obj.Appendp(ctxt, p)
-+ q1 := p
++ return p, q
++}
+
-+ p.As = ABLT
-+ p.To.Type = obj.TYPE_BRANCH
++func stacksplitPost(ctxt *obj.Link, p *obj.Prog, pPre *obj.Prog, pPreempt *obj.Prog) *obj.Prog {
+
+ // MOVD LR, R5
+ p = obj.Appendp(ctxt, p)
-+
++ pPre.Pcond = p
+ p.As = AMOVD
+ p.From.Type = obj.TYPE_REG
+ p.From.Reg = REG_LR
+ p.To.Type = obj.TYPE_REG
+ p.To.Reg = REG_R5
-+ if q != nil {
-+ q.Pcond = p
++ if pPreempt != nil {
++ pPreempt.Pcond = p
+ }
+
+ // BL runtime.morestack(SB)
@@ -19260,13 +23084,6 @@ index 0000000..71c6fb5
+ p.As = ABR
+ p.To.Type = obj.TYPE_BRANCH
+ p.Pcond = ctxt.Cursym.Text.Link
-+
-+ // placeholder for q1's jump target
-+ p = obj.Appendp(ctxt, p)
-+
-+ p.As = obj.ANOP // zero-width place holder
-+ q1.Pcond = p
-+
+ return p
+}
+
@@ -19454,6 +23271,9 @@ index 0000000..71c6fb5
+ ASTCKC: true,
+ ASTCKE: true,
+ ASTCKF: true,
++ ANEG: true,
++ AVONE: true,
++ AVZERO: true,
+}
+
+var Links390x = obj.LinkArch{
@@ -19469,6 +23289,1069 @@ index 0000000..71c6fb5
+ Ptrsize: 8,
+ Regsize: 8,
+}
+diff --git a/src/cmd/internal/obj/s390x/vector.go b/src/cmd/internal/obj/s390x/vector.go
+new file mode 100644
+index 0000000..36b4783
+--- /dev/null
++++ b/src/cmd/internal/obj/s390x/vector.go
+@@ -0,0 +1,1057 @@
++// Copyright 2016 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++package s390x
++
++// This file contains utility functions for use when
++// assembling vector instructions.
++
++// vop returns the opcode, element size and condition
++// setting for the given (possibly extended) mnemonic.
++func vop(as int16) (opcode, es, cs uint32) {
++ switch as {
++ default:
++ return 0, 0, 0
++ case AVA:
++ return OP_VA, 0, 0
++ case AVAB:
++ return OP_VA, 0, 0
++ case AVAH:
++ return OP_VA, 1, 0
++ case AVAF:
++ return OP_VA, 2, 0
++ case AVAG:
++ return OP_VA, 3, 0
++ case AVAQ:
++ return OP_VA, 4, 0
++ case AVACC:
++ return OP_VACC, 0, 0
++ case AVACCB:
++ return OP_VACC, 0, 0
++ case AVACCH:
++ return OP_VACC, 1, 0
++ case AVACCF:
++ return OP_VACC, 2, 0
++ case AVACCG:
++ return OP_VACC, 3, 0
++ case AVACCQ:
++ return OP_VACC, 4, 0
++ case AVAC:
++ return OP_VAC, 0, 0
++ case AVACQ:
++ return OP_VAC, 4, 0
++ case AVACCC:
++ return OP_VACCC, 0, 0
++ case AVACCCQ:
++ return OP_VACCC, 4, 0
++ case AVN:
++ return OP_VN, 0, 0
++ case AVNC:
++ return OP_VNC, 0, 0
++ case AVAVG:
++ return OP_VAVG, 0, 0
++ case AVAVGB:
++ return OP_VAVG, 0, 0
++ case AVAVGH:
++ return OP_VAVG, 1, 0
++ case AVAVGF:
++ return OP_VAVG, 2, 0
++ case AVAVGG:
++ return OP_VAVG, 3, 0
++ case AVAVGL:
++ return OP_VAVGL, 0, 0
++ case AVAVGLB:
++ return OP_VAVGL, 0, 0
++ case AVAVGLH:
++ return OP_VAVGL, 1, 0
++ case AVAVGLF:
++ return OP_VAVGL, 2, 0
++ case AVAVGLG:
++ return OP_VAVGL, 3, 0
++ case AVCKSM:
++ return OP_VCKSM, 0, 0
++ case AVCEQ:
++ return OP_VCEQ, 0, 0
++ case AVCEQB:
++ return OP_VCEQ, 0, 0
++ case AVCEQH:
++ return OP_VCEQ, 1, 0
++ case AVCEQF:
++ return OP_VCEQ, 2, 0
++ case AVCEQG:
++ return OP_VCEQ, 3, 0
++ case AVCEQBS:
++ return OP_VCEQ, 0, 1
++ case AVCEQHS:
++ return OP_VCEQ, 1, 1
++ case AVCEQFS:
++ return OP_VCEQ, 2, 1
++ case AVCEQGS:
++ return OP_VCEQ, 3, 1
++ case AVCH:
++ return OP_VCH, 0, 0
++ case AVCHB:
++ return OP_VCH, 0, 0
++ case AVCHH:
++ return OP_VCH, 1, 0
++ case AVCHF:
++ return OP_VCH, 2, 0
++ case AVCHG:
++ return OP_VCH, 3, 0
++ case AVCHBS:
++ return OP_VCH, 0, 1
++ case AVCHHS:
++ return OP_VCH, 1, 1
++ case AVCHFS:
++ return OP_VCH, 2, 1
++ case AVCHGS:
++ return OP_VCH, 3, 1
++ case AVCHL:
++ return OP_VCHL, 0, 0
++ case AVCHLB:
++ return OP_VCHL, 0, 0
++ case AVCHLH:
++ return OP_VCHL, 1, 0
++ case AVCHLF:
++ return OP_VCHL, 2, 0
++ case AVCHLG:
++ return OP_VCHL, 3, 0
++ case AVCHLBS:
++ return OP_VCHL, 0, 1
++ case AVCHLHS:
++ return OP_VCHL, 1, 1
++ case AVCHLFS:
++ return OP_VCHL, 2, 1
++ case AVCHLGS:
++ return OP_VCHL, 3, 1
++ case AVCLZ:
++ return OP_VCLZ, 0, 0
++ case AVCLZB:
++ return OP_VCLZ, 0, 0
++ case AVCLZH:
++ return OP_VCLZ, 1, 0
++ case AVCLZF:
++ return OP_VCLZ, 2, 0
++ case AVCLZG:
++ return OP_VCLZ, 3, 0
++ case AVCTZ:
++ return OP_VCTZ, 0, 0
++ case AVCTZB:
++ return OP_VCTZ, 0, 0
++ case AVCTZH:
++ return OP_VCTZ, 1, 0
++ case AVCTZF:
++ return OP_VCTZ, 2, 0
++ case AVCTZG:
++ return OP_VCTZ, 3, 0
++ case AVEC:
++ return OP_VEC, 0, 0
++ case AVECB:
++ return OP_VEC, 0, 0
++ case AVECH:
++ return OP_VEC, 1, 0
++ case AVECF:
++ return OP_VEC, 2, 0
++ case AVECG:
++ return OP_VEC, 3, 0
++ case AVECL:
++ return OP_VECL, 0, 0
++ case AVECLB:
++ return OP_VECL, 0, 0
++ case AVECLH:
++ return OP_VECL, 1, 0
++ case AVECLF:
++ return OP_VECL, 2, 0
++ case AVECLG:
++ return OP_VECL, 3, 0
++ case AVERIM:
++ return OP_VERIM, 0, 0
++ case AVERIMB:
++ return OP_VERIM, 0, 0
++ case AVERIMH:
++ return OP_VERIM, 1, 0
++ case AVERIMF:
++ return OP_VERIM, 2, 0
++ case AVERIMG:
++ return OP_VERIM, 3, 0
++ case AVERLL:
++ return OP_VERLL, 0, 0
++ case AVERLLB:
++ return OP_VERLL, 0, 0
++ case AVERLLH:
++ return OP_VERLL, 1, 0
++ case AVERLLF:
++ return OP_VERLL, 2, 0
++ case AVERLLG:
++ return OP_VERLL, 3, 0
++ case AVERLLV:
++ return OP_VERLLV, 0, 0
++ case AVERLLVB:
++ return OP_VERLLV, 0, 0
++ case AVERLLVH:
++ return OP_VERLLV, 1, 0
++ case AVERLLVF:
++ return OP_VERLLV, 2, 0
++ case AVERLLVG:
++ return OP_VERLLV, 3, 0
++ case AVESLV:
++ return OP_VESLV, 0, 0
++ case AVESLVB:
++ return OP_VESLV, 0, 0
++ case AVESLVH:
++ return OP_VESLV, 1, 0
++ case AVESLVF:
++ return OP_VESLV, 2, 0
++ case AVESLVG:
++ return OP_VESLV, 3, 0
++ case AVESL:
++ return OP_VESL, 0, 0
++ case AVESLB:
++ return OP_VESL, 0, 0
++ case AVESLH:
++ return OP_VESL, 1, 0
++ case AVESLF:
++ return OP_VESL, 2, 0
++ case AVESLG:
++ return OP_VESL, 3, 0
++ case AVESRA:
++ return OP_VESRA, 0, 0
++ case AVESRAB:
++ return OP_VESRA, 0, 0
++ case AVESRAH:
++ return OP_VESRA, 1, 0
++ case AVESRAF:
++ return OP_VESRA, 2, 0
++ case AVESRAG:
++ return OP_VESRA, 3, 0
++ case AVESRAV:
++ return OP_VESRAV, 0, 0
++ case AVESRAVB:
++ return OP_VESRAV, 0, 0
++ case AVESRAVH:
++ return OP_VESRAV, 1, 0
++ case AVESRAVF:
++ return OP_VESRAV, 2, 0
++ case AVESRAVG:
++ return OP_VESRAV, 3, 0
++ case AVESRL:
++ return OP_VESRL, 0, 0
++ case AVESRLB:
++ return OP_VESRL, 0, 0
++ case AVESRLH:
++ return OP_VESRL, 1, 0
++ case AVESRLF:
++ return OP_VESRL, 2, 0
++ case AVESRLG:
++ return OP_VESRL, 3, 0
++ case AVESRLV:
++ return OP_VESRLV, 0, 0
++ case AVESRLVB:
++ return OP_VESRLV, 0, 0
++ case AVESRLVH:
++ return OP_VESRLV, 1, 0
++ case AVESRLVF:
++ return OP_VESRLV, 2, 0
++ case AVESRLVG:
++ return OP_VESRLV, 3, 0
++ case AVX:
++ return OP_VX, 0, 0
++ case AVFAE:
++ return OP_VFAE, 0, 0
++ case AVFAEB:
++ return OP_VFAE, 0, 0
++ case AVFAEH:
++ return OP_VFAE, 1, 0
++ case AVFAEF:
++ return OP_VFAE, 2, 0
++ case AVFAEBS:
++ return OP_VFAE, 0, 1
++ case AVFAEHS:
++ return OP_VFAE, 1, 1
++ case AVFAEFS:
++ return OP_VFAE, 2, 1
++ case AVFAEZB:
++ return OP_VFAE, 0, 2
++ case AVFAEZH:
++ return OP_VFAE, 1, 2
++ case AVFAEZF:
++ return OP_VFAE, 2, 2
++ case AVFAEZBS:
++ return OP_VFAE, 0, 3
++ case AVFAEZHS:
++ return OP_VFAE, 1, 3
++ case AVFAEZFS:
++ return OP_VFAE, 2, 3
++ case AVFEE:
++ return OP_VFEE, 0, 0
++ case AVFEEB:
++ return OP_VFEE, 0, 0
++ case AVFEEH:
++ return OP_VFEE, 1, 0
++ case AVFEEF:
++ return OP_VFEE, 2, 0
++ case AVFEEBS:
++ return OP_VFEE, 0, 1
++ case AVFEEHS:
++ return OP_VFEE, 1, 1
++ case AVFEEFS:
++ return OP_VFEE, 2, 1
++ case AVFEEZB:
++ return OP_VFEE, 0, 2
++ case AVFEEZH:
++ return OP_VFEE, 1, 2
++ case AVFEEZF:
++ return OP_VFEE, 2, 2
++ case AVFEEZBS:
++ return OP_VFEE, 0, 3
++ case AVFEEZHS:
++ return OP_VFEE, 1, 3
++ case AVFEEZFS:
++ return OP_VFEE, 2, 3
++ case AVFENE:
++ return OP_VFENE, 0, 0
++ case AVFENEB:
++ return OP_VFENE, 0, 0
++ case AVFENEH:
++ return OP_VFENE, 1, 0
++ case AVFENEF:
++ return OP_VFENE, 2, 0
++ case AVFENEBS:
++ return OP_VFENE, 0, 1
++ case AVFENEHS:
++ return OP_VFENE, 1, 1
++ case AVFENEFS:
++ return OP_VFENE, 2, 1
++ case AVFENEZB:
++ return OP_VFENE, 0, 2
++ case AVFENEZH:
++ return OP_VFENE, 1, 2
++ case AVFENEZF:
++ return OP_VFENE, 2, 2
++ case AVFENEZBS:
++ return OP_VFENE, 0, 3
++ case AVFENEZHS:
++ return OP_VFENE, 1, 3
++ case AVFENEZFS:
++ return OP_VFENE, 2, 3
++ case AVFA:
++ return OP_VFA, 0, 0
++ case AVFADB:
++ return OP_VFA, 3, 0
++ case AWFADB:
++ return OP_VFA, 3, 0
++ case AWFK:
++ return OP_WFK, 0, 0
++ case AWFKDB:
++ return OP_WFK, 3, 0
++ case AVFCE:
++ return OP_VFCE, 0, 0
++ case AVFCEDB:
++ return OP_VFCE, 3, 0
++ case AVFCEDBS:
++ return OP_VFCE, 3, 1
++ case AWFCEDB:
++ return OP_VFCE, 3, 0
++ case AWFCEDBS:
++ return OP_VFCE, 3, 1
++ case AVFCH:
++ return OP_VFCH, 0, 0
++ case AVFCHDB:
++ return OP_VFCH, 3, 0
++ case AVFCHDBS:
++ return OP_VFCH, 3, 1
++ case AWFCHDB:
++ return OP_VFCH, 3, 0
++ case AWFCHDBS:
++ return OP_VFCH, 3, 1
++ case AVFCHE:
++ return OP_VFCHE, 0, 0
++ case AVFCHEDB:
++ return OP_VFCHE, 3, 0
++ case AVFCHEDBS:
++ return OP_VFCHE, 3, 1
++ case AWFCHEDB:
++ return OP_VFCHE, 3, 0
++ case AWFCHEDBS:
++ return OP_VFCHE, 3, 1
++ case AWFC:
++ return OP_WFC, 0, 0
++ case AWFCDB:
++ return OP_WFC, 3, 0
++ case AVCDG:
++ return OP_VCDG, 0, 0
++ case AVCDGB:
++ return OP_VCDG, 3, 0
++ case AWCDGB:
++ return OP_VCDG, 3, 0
++ case AVCDLG:
++ return OP_VCDLG, 0, 0
++ case AVCDLGB:
++ return OP_VCDLG, 3, 0
++ case AWCDLGB:
++ return OP_VCDLG, 3, 0
++ case AVCGD:
++ return OP_VCGD, 0, 0
++ case AVCGDB:
++ return OP_VCGD, 3, 0
++ case AWCGDB:
++ return OP_VCGD, 3, 0
++ case AVCLGD:
++ return OP_VCLGD, 0, 0
++ case AVCLGDB:
++ return OP_VCLGD, 3, 0
++ case AWCLGDB:
++ return OP_VCLGD, 3, 0
++ case AVFD:
++ return OP_VFD, 0, 0
++ case AVFDDB:
++ return OP_VFD, 3, 0
++ case AWFDDB:
++ return OP_VFD, 3, 0
++ case AVLDE:
++ return OP_VLDE, 0, 0
++ case AVLDEB:
++ return OP_VLDE, 2, 0
++ case AWLDEB:
++ return OP_VLDE, 2, 0
++ case AVLED:
++ return OP_VLED, 0, 0
++ case AVLEDB:
++ return OP_VLED, 3, 0
++ case AWLEDB:
++ return OP_VLED, 3, 0
++ case AVFM:
++ return OP_VFM, 0, 0
++ case AVFMDB:
++ return OP_VFM, 3, 0
++ case AWFMDB:
++ return OP_VFM, 3, 0
++ case AVFMA:
++ return OP_VFMA, 0, 0
++ case AVFMADB:
++ return OP_VFMA, 3, 0
++ case AWFMADB:
++ return OP_VFMA, 3, 0
++ case AVFMS:
++ return OP_VFMS, 0, 0
++ case AVFMSDB:
++ return OP_VFMS, 3, 0
++ case AWFMSDB:
++ return OP_VFMS, 3, 0
++ case AVFPSO:
++ return OP_VFPSO, 0, 0
++ case AVFPSODB:
++ return OP_VFPSO, 3, 0
++ case AWFPSODB:
++ return OP_VFPSO, 3, 0
++ case AVFLCDB:
++ return OP_VFPSO, 3, 0
++ case AWFLCDB:
++ return OP_VFPSO, 3, 0
++ case AVFLNDB:
++ return OP_VFPSO, 3, 1
++ case AWFLNDB:
++ return OP_VFPSO, 3, 1
++ case AVFLPDB:
++ return OP_VFPSO, 3, 2
++ case AWFLPDB:
++ return OP_VFPSO, 3, 2
++ case AVFSQ:
++ return OP_VFSQ, 0, 0
++ case AVFSQDB:
++ return OP_VFSQ, 3, 0
++ case AWFSQDB:
++ return OP_VFSQ, 3, 0
++ case AVFS:
++ return OP_VFS, 0, 0
++ case AVFSDB:
++ return OP_VFS, 3, 0
++ case AWFSDB:
++ return OP_VFS, 3, 0
++ case AVFTCI:
++ return OP_VFTCI, 0, 0
++ case AVFTCIDB:
++ return OP_VFTCI, 3, 0
++ case AWFTCIDB:
++ return OP_VFTCI, 3, 0
++ case AVGFM:
++ return OP_VGFM, 0, 0
++ case AVGFMB:
++ return OP_VGFM, 0, 0
++ case AVGFMH:
++ return OP_VGFM, 1, 0
++ case AVGFMF:
++ return OP_VGFM, 2, 0
++ case AVGFMG:
++ return OP_VGFM, 3, 0
++ case AVGFMA:
++ return OP_VGFMA, 0, 0
++ case AVGFMAB:
++ return OP_VGFMA, 0, 0
++ case AVGFMAH:
++ return OP_VGFMA, 1, 0
++ case AVGFMAF:
++ return OP_VGFMA, 2, 0
++ case AVGFMAG:
++ return OP_VGFMA, 3, 0
++ case AVGEF:
++ return OP_VGEF, 0, 0
++ case AVGEG:
++ return OP_VGEG, 0, 0
++ case AVGBM:
++ return OP_VGBM, 0, 0
++ case AVZERO:
++ return OP_VGBM, 0, 0
++ case AVONE:
++ return OP_VGBM, 0, 0
++ case AVGM:
++ return OP_VGM, 0, 0
++ case AVGMB:
++ return OP_VGM, 0, 0
++ case AVGMH:
++ return OP_VGM, 1, 0
++ case AVGMF:
++ return OP_VGM, 2, 0
++ case AVGMG:
++ return OP_VGM, 3, 0
++ case AVISTR:
++ return OP_VISTR, 0, 0
++ case AVISTRB:
++ return OP_VISTR, 0, 0
++ case AVISTRH:
++ return OP_VISTR, 1, 0
++ case AVISTRF:
++ return OP_VISTR, 2, 0
++ case AVISTRBS:
++ return OP_VISTR, 0, 1
++ case AVISTRHS:
++ return OP_VISTR, 1, 1
++ case AVISTRFS:
++ return OP_VISTR, 2, 1
++ case AVL:
++ return OP_VL, 0, 0
++ case AVLR:
++ return OP_VLR, 0, 0
++ case AVLREP:
++ return OP_VLREP, 0, 0
++ case AVLREPB:
++ return OP_VLREP, 0, 0
++ case AVLREPH:
++ return OP_VLREP, 1, 0
++ case AVLREPF:
++ return OP_VLREP, 2, 0
++ case AVLREPG:
++ return OP_VLREP, 3, 0
++ case AVLC:
++ return OP_VLC, 0, 0
++ case AVLCB:
++ return OP_VLC, 0, 0
++ case AVLCH:
++ return OP_VLC, 1, 0
++ case AVLCF:
++ return OP_VLC, 2, 0
++ case AVLCG:
++ return OP_VLC, 3, 0
++ case AVLEH:
++ return OP_VLEH, 0, 0
++ case AVLEF:
++ return OP_VLEF, 0, 0
++ case AVLEG:
++ return OP_VLEG, 0, 0
++ case AVLEB:
++ return OP_VLEB, 0, 0
++ case AVLEIH:
++ return OP_VLEIH, 0, 0
++ case AVLEIF:
++ return OP_VLEIF, 0, 0
++ case AVLEIG:
++ return OP_VLEIG, 0, 0
++ case AVLEIB:
++ return OP_VLEIB, 0, 0
++ case AVFI:
++ return OP_VFI, 0, 0
++ case AVFIDB:
++ return OP_VFI, 3, 0
++ case AWFIDB:
++ return OP_VFI, 3, 0
++ case AVLGV:
++ return OP_VLGV, 0, 0
++ case AVLGVB:
++ return OP_VLGV, 0, 0
++ case AVLGVH:
++ return OP_VLGV, 1, 0
++ case AVLGVF:
++ return OP_VLGV, 2, 0
++ case AVLGVG:
++ return OP_VLGV, 3, 0
++ case AVLLEZ:
++ return OP_VLLEZ, 0, 0
++ case AVLLEZB:
++ return OP_VLLEZ, 0, 0
++ case AVLLEZH:
++ return OP_VLLEZ, 1, 0
++ case AVLLEZF:
++ return OP_VLLEZ, 2, 0
++ case AVLLEZG:
++ return OP_VLLEZ, 3, 0
++ case AVLM:
++ return OP_VLM, 0, 0
++ case AVLP:
++ return OP_VLP, 0, 0
++ case AVLPB:
++ return OP_VLP, 0, 0
++ case AVLPH:
++ return OP_VLP, 1, 0
++ case AVLPF:
++ return OP_VLP, 2, 0
++ case AVLPG:
++ return OP_VLP, 3, 0
++ case AVLBB:
++ return OP_VLBB, 0, 0
++ case AVLVG:
++ return OP_VLVG, 0, 0
++ case AVLVGB:
++ return OP_VLVG, 0, 0
++ case AVLVGH:
++ return OP_VLVG, 1, 0
++ case AVLVGF:
++ return OP_VLVG, 2, 0
++ case AVLVGG:
++ return OP_VLVG, 3, 0
++ case AVLVGP:
++ return OP_VLVGP, 0, 0
++ case AVLL:
++ return OP_VLL, 0, 0
++ case AVMX:
++ return OP_VMX, 0, 0
++ case AVMXB:
++ return OP_VMX, 0, 0
++ case AVMXH:
++ return OP_VMX, 1, 0
++ case AVMXF:
++ return OP_VMX, 2, 0
++ case AVMXG:
++ return OP_VMX, 3, 0
++ case AVMXL:
++ return OP_VMXL, 0, 0
++ case AVMXLB:
++ return OP_VMXL, 0, 0
++ case AVMXLH:
++ return OP_VMXL, 1, 0
++ case AVMXLF:
++ return OP_VMXL, 2, 0
++ case AVMXLG:
++ return OP_VMXL, 3, 0
++ case AVMRH:
++ return OP_VMRH, 0, 0
++ case AVMRHB:
++ return OP_VMRH, 0, 0
++ case AVMRHH:
++ return OP_VMRH, 1, 0
++ case AVMRHF:
++ return OP_VMRH, 2, 0
++ case AVMRHG:
++ return OP_VMRH, 3, 0
++ case AVMRL:
++ return OP_VMRL, 0, 0
++ case AVMRLB:
++ return OP_VMRL, 0, 0
++ case AVMRLH:
++ return OP_VMRL, 1, 0
++ case AVMRLF:
++ return OP_VMRL, 2, 0
++ case AVMRLG:
++ return OP_VMRL, 3, 0
++ case AVMN:
++ return OP_VMN, 0, 0
++ case AVMNB:
++ return OP_VMN, 0, 0
++ case AVMNH:
++ return OP_VMN, 1, 0
++ case AVMNF:
++ return OP_VMN, 2, 0
++ case AVMNG:
++ return OP_VMN, 3, 0
++ case AVMNL:
++ return OP_VMNL, 0, 0
++ case AVMNLB:
++ return OP_VMNL, 0, 0
++ case AVMNLH:
++ return OP_VMNL, 1, 0
++ case AVMNLF:
++ return OP_VMNL, 2, 0
++ case AVMNLG:
++ return OP_VMNL, 3, 0
++ case AVMAE:
++ return OP_VMAE, 0, 0
++ case AVMAEB:
++ return OP_VMAE, 0, 0
++ case AVMAEH:
++ return OP_VMAE, 1, 0
++ case AVMAEF:
++ return OP_VMAE, 2, 0
++ case AVMAH:
++ return OP_VMAH, 0, 0
++ case AVMAHB:
++ return OP_VMAH, 0, 0
++ case AVMAHH:
++ return OP_VMAH, 1, 0
++ case AVMAHF:
++ return OP_VMAH, 2, 0
++ case AVMALE:
++ return OP_VMALE, 0, 0
++ case AVMALEB:
++ return OP_VMALE, 0, 0
++ case AVMALEH:
++ return OP_VMALE, 1, 0
++ case AVMALEF:
++ return OP_VMALE, 2, 0
++ case AVMALH:
++ return OP_VMALH, 0, 0
++ case AVMALHB:
++ return OP_VMALH, 0, 0
++ case AVMALHH:
++ return OP_VMALH, 1, 0
++ case AVMALHF:
++ return OP_VMALH, 2, 0
++ case AVMALO:
++ return OP_VMALO, 0, 0
++ case AVMALOB:
++ return OP_VMALO, 0, 0
++ case AVMALOH:
++ return OP_VMALO, 1, 0
++ case AVMALOF:
++ return OP_VMALO, 2, 0
++ case AVMAL:
++ return OP_VMAL, 0, 0
++ case AVMALB:
++ return OP_VMAL, 0, 0
++ case AVMALHW:
++ return OP_VMAL, 1, 0
++ case AVMALF:
++ return OP_VMAL, 2, 0
++ case AVMAO:
++ return OP_VMAO, 0, 0
++ case AVMAOB:
++ return OP_VMAO, 0, 0
++ case AVMAOH:
++ return OP_VMAO, 1, 0
++ case AVMAOF:
++ return OP_VMAO, 2, 0
++ case AVME:
++ return OP_VME, 0, 0
++ case AVMEB:
++ return OP_VME, 0, 0
++ case AVMEH:
++ return OP_VME, 1, 0
++ case AVMEF:
++ return OP_VME, 2, 0
++ case AVMH:
++ return OP_VMH, 0, 0
++ case AVMHB:
++ return OP_VMH, 0, 0
++ case AVMHH:
++ return OP_VMH, 1, 0
++ case AVMHF:
++ return OP_VMH, 2, 0
++ case AVMLE:
++ return OP_VMLE, 0, 0
++ case AVMLEB:
++ return OP_VMLE, 0, 0
++ case AVMLEH:
++ return OP_VMLE, 1, 0
++ case AVMLEF:
++ return OP_VMLE, 2, 0
++ case AVMLH:
++ return OP_VMLH, 0, 0
++ case AVMLHB:
++ return OP_VMLH, 0, 0
++ case AVMLHH:
++ return OP_VMLH, 1, 0
++ case AVMLHF:
++ return OP_VMLH, 2, 0
++ case AVMLO:
++ return OP_VMLO, 0, 0
++ case AVMLOB:
++ return OP_VMLO, 0, 0
++ case AVMLOH:
++ return OP_VMLO, 1, 0
++ case AVMLOF:
++ return OP_VMLO, 2, 0
++ case AVML:
++ return OP_VML, 0, 0
++ case AVMLB:
++ return OP_VML, 0, 0
++ case AVMLHW:
++ return OP_VML, 1, 0
++ case AVMLF:
++ return OP_VML, 2, 0
++ case AVMO:
++ return OP_VMO, 0, 0
++ case AVMOB:
++ return OP_VMO, 0, 0
++ case AVMOH:
++ return OP_VMO, 1, 0
++ case AVMOF:
++ return OP_VMO, 2, 0
++ case AVNO:
++ return OP_VNO, 0, 0
++ case AVNOT:
++ return OP_VNO, 0, 0
++ case AVO:
++ return OP_VO, 0, 0
++ case AVPK:
++ return OP_VPK, 0, 0
++ case AVPKH:
++ return OP_VPK, 1, 0
++ case AVPKF:
++ return OP_VPK, 2, 0
++ case AVPKG:
++ return OP_VPK, 3, 0
++ case AVPKLS:
++ return OP_VPKLS, 0, 0
++ case AVPKLSH:
++ return OP_VPKLS, 1, 0
++ case AVPKLSF:
++ return OP_VPKLS, 2, 0
++ case AVPKLSG:
++ return OP_VPKLS, 3, 0
++ case AVPKLSHS:
++ return OP_VPKLS, 1, 1
++ case AVPKLSFS:
++ return OP_VPKLS, 2, 1
++ case AVPKLSGS:
++ return OP_VPKLS, 3, 1
++ case AVPKS:
++ return OP_VPKS, 0, 0
++ case AVPKSH:
++ return OP_VPKS, 1, 0
++ case AVPKSF:
++ return OP_VPKS, 2, 0
++ case AVPKSG:
++ return OP_VPKS, 3, 0
++ case AVPKSHS:
++ return OP_VPKS, 1, 1
++ case AVPKSFS:
++ return OP_VPKS, 2, 1
++ case AVPKSGS:
++ return OP_VPKS, 3, 1
++ case AVPERM:
++ return OP_VPERM, 0, 0
++ case AVPDI:
++ return OP_VPDI, 0, 0
++ case AVPOPCT:
++ return OP_VPOPCT, 0, 0
++ case AVREP:
++ return OP_VREP, 0, 0
++ case AVREPB:
++ return OP_VREP, 0, 0
++ case AVREPH:
++ return OP_VREP, 1, 0
++ case AVREPF:
++ return OP_VREP, 2, 0
++ case AVREPG:
++ return OP_VREP, 3, 0
++ case AVREPI:
++ return OP_VREPI, 0, 0
++ case AVREPIB:
++ return OP_VREPI, 0, 0
++ case AVREPIH:
++ return OP_VREPI, 1, 0
++ case AVREPIF:
++ return OP_VREPI, 2, 0
++ case AVREPIG:
++ return OP_VREPI, 3, 0
++ case AVSCEF:
++ return OP_VSCEF, 0, 0
++ case AVSCEG:
++ return OP_VSCEG, 0, 0
++ case AVSEL:
++ return OP_VSEL, 0, 0
++ case AVSL:
++ return OP_VSL, 0, 0
++ case AVSLB:
++ return OP_VSLB, 0, 0
++ case AVSLDB:
++ return OP_VSLDB, 0, 0
++ case AVSRA:
++ return OP_VSRA, 0, 0
++ case AVSRAB:
++ return OP_VSRAB, 0, 0
++ case AVSRL:
++ return OP_VSRL, 0, 0
++ case AVSRLB:
++ return OP_VSRLB, 0, 0
++ case AVSEG:
++ return OP_VSEG, 0, 0
++ case AVSEGB:
++ return OP_VSEG, 0, 0
++ case AVSEGH:
++ return OP_VSEG, 1, 0
++ case AVSEGF:
++ return OP_VSEG, 2, 0
++ case AVST:
++ return OP_VST, 0, 0
++ case AVSTEH:
++ return OP_VSTEH, 0, 0
++ case AVSTEF:
++ return OP_VSTEF, 0, 0
++ case AVSTEG:
++ return OP_VSTEG, 0, 0
++ case AVSTEB:
++ return OP_VSTEB, 0, 0
++ case AVSTM:
++ return OP_VSTM, 0, 0
++ case AVSTL:
++ return OP_VSTL, 0, 0
++ case AVSTRC:
++ return OP_VSTRC, 0, 0
++ case AVSTRCB:
++ return OP_VSTRC, 0, 0
++ case AVSTRCH:
++ return OP_VSTRC, 1, 0
++ case AVSTRCF:
++ return OP_VSTRC, 2, 0
++ case AVSTRCBS:
++ return OP_VSTRC, 0, 1
++ case AVSTRCHS:
++ return OP_VSTRC, 1, 1
++ case AVSTRCFS:
++ return OP_VSTRC, 2, 1
++ case AVSTRCZB:
++ return OP_VSTRC, 0, 2
++ case AVSTRCZH:
++ return OP_VSTRC, 1, 2
++ case AVSTRCZF:
++ return OP_VSTRC, 2, 2
++ case AVSTRCZBS:
++ return OP_VSTRC, 0, 3
++ case AVSTRCZHS:
++ return OP_VSTRC, 1, 3
++ case AVSTRCZFS:
++ return OP_VSTRC, 2, 3
++ case AVS:
++ return OP_VS, 0, 0
++ case AVSB:
++ return OP_VS, 0, 0
++ case AVSH:
++ return OP_VS, 1, 0
++ case AVSF:
++ return OP_VS, 2, 0
++ case AVSG:
++ return OP_VS, 3, 0
++ case AVSQ:
++ return OP_VS, 4, 0
++ case AVSCBI:
++ return OP_VSCBI, 0, 0
++ case AVSCBIB:
++ return OP_VSCBI, 0, 0
++ case AVSCBIH:
++ return OP_VSCBI, 1, 0
++ case AVSCBIF:
++ return OP_VSCBI, 2, 0
++ case AVSCBIG:
++ return OP_VSCBI, 3, 0
++ case AVSCBIQ:
++ return OP_VSCBI, 4, 0
++ case AVSBCBI:
++ return OP_VSBCBI, 0, 0
++ case AVSBCBIQ:
++ return OP_VSBCBI, 4, 0
++ case AVSBI:
++ return OP_VSBI, 0, 0
++ case AVSBIQ:
++ return OP_VSBI, 4, 0
++ case AVSUMG:
++ return OP_VSUMG, 0, 0
++ case AVSUMGH:
++ return OP_VSUMG, 1, 0
++ case AVSUMGF:
++ return OP_VSUMG, 2, 0
++ case AVSUMQ:
++ return OP_VSUMQ, 0, 0
++ case AVSUMQF:
++ return OP_VSUMQ, 1, 0
++ case AVSUMQG:
++ return OP_VSUMQ, 2, 0
++ case AVSUM:
++ return OP_VSUM, 0, 0
++ case AVSUMB:
++ return OP_VSUM, 0, 0
++ case AVSUMH:
++ return OP_VSUM, 1, 0
++ case AVTM:
++ return OP_VTM, 0, 0
++ case AVUPH:
++ return OP_VUPH, 0, 0
++ case AVUPHB:
++ return OP_VUPH, 0, 0
++ case AVUPHH:
++ return OP_VUPH, 1, 0
++ case AVUPHF:
++ return OP_VUPH, 2, 0
++ case AVUPLH:
++ return OP_VUPLH, 0, 0
++ case AVUPLHB:
++ return OP_VUPLH, 0, 0
++ case AVUPLHH:
++ return OP_VUPLH, 1, 0
++ case AVUPLHF:
++ return OP_VUPLH, 2, 0
++ case AVUPLL:
++ return OP_VUPLL, 0, 0
++ case AVUPLLB:
++ return OP_VUPLL, 0, 0
++ case AVUPLLH:
++ return OP_VUPLL, 1, 0
++ case AVUPLLF:
++ return OP_VUPLL, 2, 0
++ case AVUPL:
++ return OP_VUPL, 0, 0
++ case AVUPLB:
++ return OP_VUPL, 0, 0
++ case AVUPLHW:
++ return OP_VUPL, 1, 0
++ case AVUPLF:
++ return OP_VUPL, 2, 0
++ }
++}
++
++// singleElementMask returns the single element mask bits required for the
++// given instruction.
++func singleElementMask(as int16) uint32 {
++ switch as {
++ case AWFADB,
++ AWFK,
++ AWFKDB,
++ AWFCEDB,
++ AWFCEDBS,
++ AWFCHDB,
++ AWFCHDBS,
++ AWFCHEDB,
++ AWFCHEDBS,
++ AWFC,
++ AWFCDB,
++ AWCDGB,
++ AWCDLGB,
++ AWCGDB,
++ AWCLGDB,
++ AWFDDB,
++ AWLDEB,
++ AWLEDB,
++ AWFMDB,
++ AWFMADB,
++ AWFMSDB,
++ AWFPSODB,
++ AWFLCDB,
++ AWFLNDB,
++ AWFLPDB,
++ AWFSQDB,
++ AWFSDB,
++ AWFTCIDB,
++ AWFIDB:
++ return 8
++ }
++ return 0
++}
diff --git a/src/cmd/internal/obj/util.go b/src/cmd/internal/obj/util.go
index 5103299..06391cb 100644
--- a/src/cmd/internal/obj/util.go
@@ -19489,8 +24372,282 @@ index 5103299..06391cb 100644
AMask = 1<<12 - 1 // AND with this to use the opcode as an array index.
)
+diff --git a/src/cmd/internal/obj/x86/a.out.go b/src/cmd/internal/obj/x86/a.out.go
+index 12eaa90..dacf612 100644
+--- a/src/cmd/internal/obj/x86/a.out.go
++++ b/src/cmd/internal/obj/x86/a.out.go
+@@ -289,8 +289,6 @@ const (
+ AFMOVX
+ AFMOVXP
+
+- AFCOMB
+- AFCOMBP
+ AFCOMD
+ AFCOMDP
+ AFCOMDPP
+@@ -620,14 +618,7 @@ const (
+ APADDUSW
+ APADDW
+ APAND
+- APANDB
+- APANDL
+ APANDN
+- APANDSB
+- APANDSW
+- APANDUSB
+- APANDUSW
+- APANDW
+ APAVGB
+ APAVGW
+ APCMPEQB
+@@ -644,23 +635,6 @@ const (
+ APEXTRD
+ APEXTRQ
+ APEXTRW
+- APFACC
+- APFADD
+- APFCMPEQ
+- APFCMPGE
+- APFCMPGT
+- APFMAX
+- APFMIN
+- APFMUL
+- APFNACC
+- APFPNACC
+- APFRCP
+- APFRCPI2T
+- APFRCPIT1
+- APFRSQIT1
+- APFRSQRT
+- APFSUB
+- APFSUBR
+ APHADDD
+ APHADDSW
+ APHADDW
+@@ -691,7 +665,6 @@ const (
+ APMOVZXWD
+ APMOVZXWQ
+ APMULDQ
+- APMULHRW
+ APMULHUW
+ APMULHW
+ APMULLD
+@@ -722,7 +695,6 @@ const (
+ APSUBUSB
+ APSUBUSW
+ APSUBW
+- APSWAPL
+ APUNPCKHBW
+ APUNPCKHLQ
+ APUNPCKHQDQ
+@@ -761,11 +733,6 @@ const (
+ AUNPCKLPS
+ AXORPD
+ AXORPS
+-
+- APF2IW
+- APF2IL
+- API2FW
+- API2FL
+ ARETFW
+ ARETFL
+ ARETFQ
+diff --git a/src/cmd/internal/obj/x86/anames.go b/src/cmd/internal/obj/x86/anames.go
+index 1875eae..3b59e2f 100644
+--- a/src/cmd/internal/obj/x86/anames.go
++++ b/src/cmd/internal/obj/x86/anames.go
+@@ -255,8 +255,6 @@ var Anames = []string{
+ "FMOVWP",
+ "FMOVX",
+ "FMOVXP",
+- "FCOMB",
+- "FCOMBP",
+ "FCOMD",
+ "FCOMDP",
+ "FCOMDPP",
+@@ -569,14 +567,7 @@ var Anames = []string{
+ "PADDUSW",
+ "PADDW",
+ "PAND",
+- "PANDB",
+- "PANDL",
+ "PANDN",
+- "PANDSB",
+- "PANDSW",
+- "PANDUSB",
+- "PANDUSW",
+- "PANDW",
+ "PAVGB",
+ "PAVGW",
+ "PCMPEQB",
+@@ -593,23 +584,6 @@ var Anames = []string{
+ "PEXTRD",
+ "PEXTRQ",
+ "PEXTRW",
+- "PFACC",
+- "PFADD",
+- "PFCMPEQ",
+- "PFCMPGE",
+- "PFCMPGT",
+- "PFMAX",
+- "PFMIN",
+- "PFMUL",
+- "PFNACC",
+- "PFPNACC",
+- "PFRCP",
+- "PFRCPI2T",
+- "PFRCPIT1",
+- "PFRSQIT1",
+- "PFRSQRT",
+- "PFSUB",
+- "PFSUBR",
+ "PHADDD",
+ "PHADDSW",
+ "PHADDW",
+@@ -640,7 +614,6 @@ var Anames = []string{
+ "PMOVZXWD",
+ "PMOVZXWQ",
+ "PMULDQ",
+- "PMULHRW",
+ "PMULHUW",
+ "PMULHW",
+ "PMULLD",
+@@ -671,7 +644,6 @@ var Anames = []string{
+ "PSUBUSB",
+ "PSUBUSW",
+ "PSUBW",
+- "PSWAPL",
+ "PUNPCKHBW",
+ "PUNPCKHLQ",
+ "PUNPCKHQDQ",
+@@ -710,10 +682,6 @@ var Anames = []string{
+ "UNPCKLPS",
+ "XORPD",
+ "XORPS",
+- "PF2IW",
+- "PF2IL",
+- "PI2FW",
+- "PI2FL",
+ "RETFW",
+ "RETFL",
+ "RETFQ",
+diff --git a/src/cmd/internal/obj/x86/asm6.go b/src/cmd/internal/obj/x86/asm6.go
+index 4ed1d87..1153506 100644
+--- a/src/cmd/internal/obj/x86/asm6.go
++++ b/src/cmd/internal/obj/x86/asm6.go
+@@ -184,7 +184,6 @@ const (
+ Zm2_r
+ Zm_r_xm
+ Zm_r_i_xm
+- Zm_r_3d
+ Zm_r_xm_nr
+ Zr_m_xm_nr
+ Zibm_r /* mmx1,mmx2/mem64,imm8 */
+@@ -753,10 +752,6 @@ var yxrrl = []ytab{
+ {Yxr, Ynone, Yrl, Zm_r, 1},
+ }
+
+-var ymfp = []ytab{
+- {Ymm, Ynone, Ymr, Zm_r_3d, 1},
+-}
+-
+ var ymrxr = []ytab{
+ {Ymr, Ynone, Yxr, Zm_r, 1},
+ {Yxm, Ynone, Yxr, Zm_r_xm, 1},
+@@ -1085,7 +1080,6 @@ var optab =
+ {ACVTPD2PS, yxm, Pe, [23]uint8{0x5a}},
+ {ACVTPS2PL, yxcvm1, Px, [23]uint8{Pe, 0x5b, Pm, 0x2d}},
+ {ACVTPS2PD, yxm, Pm, [23]uint8{0x5a}},
+- {API2FW, ymfp, Px, [23]uint8{0x0c}},
+ {ACVTSD2SL, yxcvfl, Pf2, [23]uint8{0x2d}},
+ {ACVTSD2SQ, yxcvfq, Pw, [23]uint8{Pf2, 0x2d}},
+ {ACVTSD2SS, yxm, Pf2, [23]uint8{0x5a}},
+@@ -1303,26 +1297,6 @@ var optab =
+ {APEXTRB, yextr, Pq, [23]uint8{0x3a, 0x14, 00}},
+ {APEXTRD, yextr, Pq, [23]uint8{0x3a, 0x16, 00}},
+ {APEXTRQ, yextr, Pq3, [23]uint8{0x3a, 0x16, 00}},
+- {APF2IL, ymfp, Px, [23]uint8{0x1d}},
+- {APF2IW, ymfp, Px, [23]uint8{0x1c}},
+- {API2FL, ymfp, Px, [23]uint8{0x0d}},
+- {APFACC, ymfp, Px, [23]uint8{0xae}},
+- {APFADD, ymfp, Px, [23]uint8{0x9e}},
+- {APFCMPEQ, ymfp, Px, [23]uint8{0xb0}},
+- {APFCMPGE, ymfp, Px, [23]uint8{0x90}},
+- {APFCMPGT, ymfp, Px, [23]uint8{0xa0}},
+- {APFMAX, ymfp, Px, [23]uint8{0xa4}},
+- {APFMIN, ymfp, Px, [23]uint8{0x94}},
+- {APFMUL, ymfp, Px, [23]uint8{0xb4}},
+- {APFNACC, ymfp, Px, [23]uint8{0x8a}},
+- {APFPNACC, ymfp, Px, [23]uint8{0x8e}},
+- {APFRCP, ymfp, Px, [23]uint8{0x96}},
+- {APFRCPIT1, ymfp, Px, [23]uint8{0xa6}},
+- {APFRCPI2T, ymfp, Px, [23]uint8{0xb6}},
+- {APFRSQIT1, ymfp, Px, [23]uint8{0xa7}},
+- {APFRSQRT, ymfp, Px, [23]uint8{0x97}},
+- {APFSUB, ymfp, Px, [23]uint8{0x9a}},
+- {APFSUBR, ymfp, Px, [23]uint8{0xaa}},
+ {APHADDD, ymmxmm0f38, Px, [23]uint8{0x0F, 0x38, 0x02, 0, 0x66, 0x0F, 0x38, 0x02, 0}},
+ {APHADDSW, yxm_q4, Pq4, [23]uint8{0x03}},
+ {APHADDW, yxm_q4, Pq4, [23]uint8{0x01}},
+@@ -1353,7 +1327,6 @@ var optab =
+ {APMOVZXWD, yxm_q4, Pq4, [23]uint8{0x33}},
+ {APMOVZXWQ, yxm_q4, Pq4, [23]uint8{0x34}},
+ {APMULDQ, yxm_q4, Pq4, [23]uint8{0x28}},
+- {APMULHRW, ymfp, Px, [23]uint8{0xb7}},
+ {APMULHUW, ymm, Py1, [23]uint8{0xe4, Pe, 0xe4}},
+ {APMULHW, ymm, Py1, [23]uint8{0xe5, Pe, 0xe5}},
+ {APMULLD, yxm_q4, Pq4, [23]uint8{0x40}},
+@@ -1395,7 +1368,6 @@ var optab =
+ {APSUBUSB, yxm, Pe, [23]uint8{0xd8}},
+ {APSUBUSW, yxm, Pe, [23]uint8{0xd9}},
+ {APSUBW, yxm, Pe, [23]uint8{0xf9}},
+- {APSWAPL, ymfp, Px, [23]uint8{0xbb}},
+ {APUNPCKHBW, ymm, Py1, [23]uint8{0x68, Pe, 0x68}},
+ {APUNPCKHLQ, ymm, Py1, [23]uint8{0x6a, Pe, 0x6a}},
+ {APUNPCKHQDQ, yxm, Pe, [23]uint8{0x6d}},
+@@ -1553,8 +1525,6 @@ var optab =
+ {AFCMOVNE, yfcmv, Px, [23]uint8{0xdb, 01}},
+ {AFCMOVNU, yfcmv, Px, [23]uint8{0xdb, 03}},
+ {AFCMOVUN, yfcmv, Px, [23]uint8{0xda, 03}},
+- {AFCOMB, nil, 0, [23]uint8{}},
+- {AFCOMBP, nil, 0, [23]uint8{}},
+ {AFCOMD, yfadd, Px, [23]uint8{0xdc, 02, 0xd8, 02, 0xdc, 02}}, /* botch */
+ {AFCOMDP, yfadd, Px, [23]uint8{0xdc, 03, 0xd8, 03, 0xdc, 03}}, /* botch */
+ {AFCOMDPP, ycompp, Px, [23]uint8{0xde, 03}},
+@@ -3533,15 +3503,6 @@ func doasm(ctxt *obj.Link, p *obj.Prog) {
+ ctxt.Andptr[0] = byte(p.To.Offset)
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+- case Zm_r_3d:
+- ctxt.Andptr[0] = 0x0f
+- ctxt.Andptr = ctxt.Andptr[1:]
+- ctxt.Andptr[0] = 0x0f
+- ctxt.Andptr = ctxt.Andptr[1:]
+- asmand(ctxt, p, &p.From, &p.To)
+- ctxt.Andptr[0] = byte(op)
+- ctxt.Andptr = ctxt.Andptr[1:]
+-
+ case Zibm_r, Zibr_m:
+ for {
+ tmp1 := z
+@@ -4595,15 +4556,6 @@ func asmins(ctxt *obj.Link, p *obj.Prog) {
+ ctxt.Andptr = ctxt.And[:]
+ ctxt.Asmode = int(p.Mode)
+
+- if p.As == obj.AUSEFIELD {
+- r := obj.Addrel(ctxt.Cursym)
+- r.Off = 0
+- r.Siz = 0
+- r.Sym = p.From.Sym
+- r.Type = obj.R_USEFIELD
+- return
+- }
+-
+ if ctxt.Headtype == obj.Hnacl && p.Mode == 32 {
+ switch p.As {
+ case obj.ARET:
diff --git a/src/cmd/internal/objfile/disasm.go b/src/cmd/internal/objfile/disasm.go
-index 6495dfb..741f4ed 100644
+index f038883..b100830 100644
--- a/src/cmd/internal/objfile/disasm.go
+++ b/src/cmd/internal/objfile/disasm.go
@@ -245,4 +245,5 @@ var byteOrders = map[string]binary.ByteOrder{
@@ -19672,7 +24829,7 @@ index ca8eabb..bf96661 100644
}
diff --git a/src/cmd/link/internal/ld/dwarf.go b/src/cmd/link/internal/ld/dwarf.go
-index 563600d..3ed7b35 100644
+index a96b37a..96c3503 100644
--- a/src/cmd/link/internal/ld/dwarf.go
+++ b/src/cmd/link/internal/ld/dwarf.go
@@ -1715,7 +1715,7 @@ func writelines() {
@@ -19748,7 +24905,7 @@ index 563600d..3ed7b35 100644
putpccfadelta(int64(nextpc)-int64(pcsp.pc), int64(pcsp.value))
} else {
putpccfadelta(int64(nextpc)-int64(pcsp.pc), int64(Thearch.Ptrsize)+int64(pcsp.value))
-@@ -2235,7 +2256,7 @@ func dwarfaddshstrings(shstrtab *LSym) {
+@@ -2237,7 +2258,7 @@ func dwarfaddshstrings(shstrtab *LSym) {
elfstrdbg[ElfStrGDBScripts] = Addstring(shstrtab, ".debug_gdb_scripts")
if Linkmode == LinkExternal {
switch Thearch.Thechar {
@@ -19757,7 +24914,7 @@ index 563600d..3ed7b35 100644
elfstrdbg[ElfStrRelDebugInfo] = Addstring(shstrtab, ".rela.debug_info")
elfstrdbg[ElfStrRelDebugAranges] = Addstring(shstrtab, ".rela.debug_aranges")
elfstrdbg[ElfStrRelDebugLine] = Addstring(shstrtab, ".rela.debug_line")
-@@ -2288,7 +2309,7 @@ func dwarfaddelfsectionsyms() {
+@@ -2290,7 +2311,7 @@ func dwarfaddelfsectionsyms() {
func dwarfaddelfrelocheader(elfstr int, shdata *ElfShdr, off int64, size int64) {
sh := newElfShdr(elfstrdbg[elfstr])
switch Thearch.Thechar {
@@ -20128,8 +25285,73 @@ index 73d23c6..75dc7e2 100644
RV_CHECK_OVERFLOW = 1 << 8
RV_TYPE_MASK = RV_CHECK_OVERFLOW - 1
)
+diff --git a/src/cmd/link/internal/ld/pobj.go b/src/cmd/link/internal/ld/pobj.go
+index 808d377..9ec14c2 100644
+--- a/src/cmd/link/internal/ld/pobj.go
++++ b/src/cmd/link/internal/ld/pobj.go
+@@ -119,33 +119,6 @@ func Ldmain() {
+ obj.Flagstr("memprofile", "write memory profile to `file`", &memprofile)
+ obj.Flagint64("memprofilerate", "set runtime.MemProfileRate to `rate`", &memprofilerate)
+
+- // Clumsy hack to preserve old two-argument -X name val syntax for old scripts.
+- // Rewrite that syntax into new syntax -X name=val.
+- // TODO(rsc): Delete this hack in Go 1.6 or later.
+- var args []string
+- for i := 0; i < len(os.Args); i++ {
+- arg := os.Args[i]
+- if (arg == "-X" || arg == "--X") && i+2 < len(os.Args) && !strings.Contains(os.Args[i+1], "=") {
+- fmt.Fprintf(os.Stderr, "link: warning: option %s %s %s may not work in future releases; use %s %s=%s\n",
+- arg, os.Args[i+1], os.Args[i+2],
+- arg, os.Args[i+1], os.Args[i+2])
+- args = append(args, arg)
+- args = append(args, os.Args[i+1]+"="+os.Args[i+2])
+- i += 2
+- continue
+- }
+- if (strings.HasPrefix(arg, "-X=") || strings.HasPrefix(arg, "--X=")) && i+1 < len(os.Args) && strings.Count(arg, "=") == 1 {
+- fmt.Fprintf(os.Stderr, "link: warning: option %s %s may not work in future releases; use %s=%s\n",
+- arg, os.Args[i+1],
+- arg, os.Args[i+1])
+- args = append(args, arg+"="+os.Args[i+1])
+- i++
+- continue
+- }
+- args = append(args, arg)
+- }
+- os.Args = args
+-
+ obj.Flagparse(usage)
+
+ startProfile()
+diff --git a/src/cmd/link/internal/ld/sym.go b/src/cmd/link/internal/ld/sym.go
+index 731f3ed..6122b85 100644
+--- a/src/cmd/link/internal/ld/sym.go
++++ b/src/cmd/link/internal/ld/sym.go
+@@ -34,8 +34,6 @@ package ld
+ import (
+ "cmd/internal/obj"
+ "log"
+- "os"
+- "path/filepath"
+ "strconv"
+ )
+
+@@ -70,13 +68,6 @@ func linknew(arch *LinkArch) *Link {
+ log.Fatalf("invalid goarch %s (want %s)", p, arch.Name)
+ }
+
+- var buf string
+- buf, _ = os.Getwd()
+- if buf == "" {
+- buf = "/???"
+- }
+- buf = filepath.ToSlash(buf)
+-
+ ctxt.Headtype = headtype(obj.Getgoos())
+ if ctxt.Headtype < 0 {
+ log.Fatalf("unknown goos %s", obj.Getgoos())
diff --git a/src/cmd/link/internal/ld/symtab.go b/src/cmd/link/internal/ld/symtab.go
-index 3e6169e..78198eb 100644
+index 3e6169e..9416d1e 100644
--- a/src/cmd/link/internal/ld/symtab.go
+++ b/src/cmd/link/internal/ld/symtab.go
@@ -67,7 +67,7 @@ func putelfstr(s string) int {
@@ -20141,7 +25363,19 @@ index 3e6169e..78198eb 100644
Thearch.Lput(uint32(off))
Cput(uint8(info))
Cput(uint8(other))
-@@ -562,6 +562,7 @@ func symtab() {
+@@ -215,6 +215,11 @@ func Asmelfsym() {
+
+ dwarfaddelfsectionsyms()
+
++ // Some linkers will add a FILE sym if one is not present.
++ // Avoid having the working directory inserted into the symbol table.
++ putelfsyment(0, 0, 0, STB_LOCAL<<4|STT_FILE, SHN_ABS, 0)
++ numelfsym++
++
+ elfbind = STB_LOCAL
+ genasmsym(putelfsym)
+
+@@ -562,6 +567,7 @@ func symtab() {
adduint(Ctxt, moduledata, uint64(len(Ctxt.Shlibs)))
adduint(Ctxt, moduledata, uint64(len(Ctxt.Shlibs)))
}
@@ -21023,72 +26257,5558 @@ index 63df8de..0122bda 100644
+ s390x.Main()
}
}
-diff --git a/src/cmd/objdump/objdump_test.go b/src/cmd/objdump/objdump_test.go
-index 8ceaba0..cd55e16 100644
---- a/src/cmd/objdump/objdump_test.go
-+++ b/src/cmd/objdump/objdump_test.go
-@@ -107,6 +107,8 @@ func TestDisasm(t *testing.T) {
- t.Skipf("skipping on %s, issue 10106", runtime.GOARCH)
- case "mips64", "mips64le":
- t.Skipf("skipping on %s, issue 12559", runtime.GOARCH)
-+ case "s390x":
-+ t.Skipf("skipping on %s", runtime.GOARCH)
- }
- testDisasm(t)
- }
-@@ -123,6 +125,8 @@ func TestDisasmExtld(t *testing.T) {
- t.Skipf("skipping on %s, issue 10106", runtime.GOARCH)
- case "mips64", "mips64le":
- t.Skipf("skipping on %s, issue 12559 and 12560", runtime.GOARCH)
-+ case "s390x":
-+ t.Skipf("skipping on %s", runtime.GOARCH)
- }
- // TODO(jsing): Reenable once openbsd/arm has external linking support.
- if runtime.GOOS == "openbsd" && runtime.GOARCH == "arm" {
-diff --git a/src/cmd/vet/asmdecl.go b/src/cmd/vet/asmdecl.go
-index e4a9871..025d3e0 100644
---- a/src/cmd/vet/asmdecl.go
-+++ b/src/cmd/vet/asmdecl.go
-@@ -65,6 +65,7 @@ var (
- asmArchAmd64p32 = asmArch{"amd64p32", 4, 4, 8, false, "SP", false}
- asmArchPpc64 = asmArch{"ppc64", 8, 8, 8, true, "R1", true}
- asmArchPpc64LE = asmArch{"ppc64le", 8, 8, 8, false, "R1", true}
-+ asmArchS390x = asmArch{"s390x", 8, 8, 8, true, "R15", true}
-
- arches = []*asmArch{
- &asmArch386,
-@@ -74,6 +75,7 @@ var (
- &asmArchAmd64p32,
- &asmArchPpc64,
- &asmArchPpc64LE,
-+ &asmArchS390x,
- }
- )
-
-diff --git a/src/crypto/aes/asm_s390x.s b/src/crypto/aes/asm_s390x.s
+diff --git a/src/cmd/newlink/auto.go b/src/cmd/newlink/auto.go
new file mode 100644
-index 0000000..c9cf166
+index 0000000..21f6d60
--- /dev/null
-+++ b/src/crypto/aes/asm_s390x.s
-@@ -0,0 +1,97 @@
-+// Copyright 2016 The Go Authors. All rights reserved.
++++ b/src/cmd/newlink/auto.go
+@@ -0,0 +1,117 @@
++// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
-+#include "textflag.h"
++// Automatic symbol generation.
+
-+// func hasAsm() bool
-+// returns whether the AES-128, AES-192 and AES-256
-+// cipher message functions are supported.
-+TEXT ·hasAsm(SB),NOSPLIT,$16-1
-+ XOR R0, R0 // set function code to 0 (query)
-+ LA 8(R15), R1
-+ WORD $0xB92E0024 // KM-Query
++// TODO(rsc): Handle go.typelink, go.track symbols.
++// TODO(rsc): Do not handle $f64. and $f32. symbols. Instead, generate those
++// from the compiler and assemblers as dupok data, and then remove autoData below.
++package main
+
-+ // check if bits 18-20 are set
-+ MOVD 8(R15), R2
-+ SRD $40, R2
-+ AND $0x38, R2 // mask bits 18-20 (00111000)
++import (
++ "cmd/internal/goobj"
++ "strconv"
++ "strings"
++)
++
++// linkerDefined lists the symbols supplied by other parts of the linker
++// (runtime.go and layout.go).
++var linkerDefined = map[string]bool{
++ "runtime.bss": true,
++ "runtime.data": true,
++ "runtime.ebss": true,
++ "runtime.edata": true,
++ "runtime.efunctab": true,
++ "runtime.end": true,
++ "runtime.enoptrbss": true,
++ "runtime.enoptrdata": true,
++ "runtime.erodata": true,
++ "runtime.etext": true,
++ "runtime.etypelink": true,
++ "runtime.functab": true,
++ "runtime.gcbss": true,
++ "runtime.gcdata": true,
++ "runtime.noptrbss": true,
++ "runtime.noptrdata": true,
++ "runtime.pclntab": true,
++ "runtime.rodata": true,
++ "runtime.text": true,
++ "runtime.typelink": true,
++}
++
++// isAuto reports whether sym is an automatically-generated data or constant symbol.
++func (p *Prog) isAuto(sym goobj.SymID) bool {
++ return strings.HasPrefix(sym.Name, "go.weak.") ||
++ strings.HasPrefix(sym.Name, "$f64.") ||
++ strings.HasPrefix(sym.Name, "$f32.") ||
++ linkerDefined[sym.Name]
++}
++
++// autoData defines the automatically generated data symbols needed by p.
++func (p *Prog) autoData() {
++ for sym := range p.Missing {
++ switch {
++ // Floating-point constants that need to be loaded from memory are
++ // written as $f64.{16 hex digits} or $f32.{8 hex digits}; the hex digits
++ // give the IEEE bit pattern of the constant. As far as the layout into
++ // memory is concerned, we interpret these as uint64 or uint32 constants.
++ case strings.HasPrefix(sym.Name, "$f64."), strings.HasPrefix(sym.Name, "$f32."):
++ size := 64
++ if sym.Name[2:4] == "32" {
++ size = 32
++ }
++ delete(p.Missing, sym)
++ fbits, err := strconv.ParseUint(sym.Name[len("$f64."):], 16, size)
++ if err != nil {
++ p.errorf("unexpected floating point symbol %s", sym)
++ continue
++ }
++ data := make([]byte, size/8)
++ if size == 64 {
++ p.byteorder.PutUint64(data, fbits)
++ } else {
++ p.byteorder.PutUint32(data, uint32(fbits))
++ }
++ p.addSym(&Sym{
++ Sym: &goobj.Sym{
++ SymID: sym,
++ Kind: goobj.SRODATA,
++ Size: size / 8,
++ },
++ Bytes: data,
++ })
++ }
++ }
++}
++
++// autoConst defines the automatically generated constant symbols needed by p.
++func (p *Prog) autoConst() {
++ for sym := range p.Missing {
++ switch {
++ case strings.HasPrefix(sym.Name, "go.weak."):
++ // weak symbol resolves to actual symbol if present, or else nil.
++ delete(p.Missing, sym)
++ targ := sym
++ targ.Name = sym.Name[len("go.weak."):]
++ var addr Addr
++ if s := p.Syms[targ]; s != nil {
++ addr = s.Addr
++ }
++ p.defineConst(sym.Name, addr)
++ }
++ }
++}
++
++// defineConst defines a new symbol with the given name and constant address.
++func (p *Prog) defineConst(name string, addr Addr) {
++ sym := goobj.SymID{Name: name}
++ p.addSym(&Sym{
++ Sym: &goobj.Sym{
++ SymID: sym,
++ Kind: goobj.SCONST,
++ },
++ Package: nil,
++ Addr: addr,
++ })
++}
+diff --git a/src/cmd/newlink/auto_test.go b/src/cmd/newlink/auto_test.go
+new file mode 100644
+index 0000000..f99e097
+--- /dev/null
++++ b/src/cmd/newlink/auto_test.go
+@@ -0,0 +1,72 @@
++// Copyright 2014 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++// Test for auto-generated symbols.
++
++// There is no test for $f64. and $f32. symbols, because those are
++// not possible to write in the assembler syntax. Instead of changing
++// the assembler to allow that, we plan to change the compilers
++// not to generate such symbols (plain dupok data is sufficient).
++
++package main
++
++import (
++ "bytes"
++ "cmd/internal/goobj"
++ "testing"
++)
++
++// Each test case is an object file, generated from a corresponding .s file.
++// The image of the autotab symbol should be a sequence of pairs of
++// identical 8-byte sequences.
++var autoTests = []string{
++ "testdata/autosection.6",
++ "testdata/autoweak.6",
++}
++
++func TestAuto(t *testing.T) {
++ for _, obj := range autoTests {
++ p := Prog{GOOS: "darwin", GOARCH: "amd64", StartSym: "start"}
++ p.omitRuntime = true
++ p.Error = func(s string) { t.Error(s) }
++ var buf bytes.Buffer
++ p.link(&buf, obj)
++ if p.NumError > 0 {
++ continue // already reported
++ }
++
++ const name = "autotab"
++ sym := p.Syms[goobj.SymID{Name: name}]
++ if sym == nil {
++ t.Errorf("%s is missing %s symbol", obj, name)
++ return
++ }
++ if sym.Size == 0 {
++ return
++ }
++
++ seg := sym.Section.Segment
++ off := sym.Addr - seg.VirtAddr
++ data := seg.Data[off : off+Addr(sym.Size)]
++ if len(data)%16 != 0 {
++ t.Errorf("%s: %s.Size = %d, want multiple of 16", obj, name, len(data))
++ return
++ }
++ Data:
++ for i := 0; i < len(data); i += 16 {
++ have := p.byteorder.Uint64(data[i : i+8])
++ want := p.byteorder.Uint64(data[i+8 : i+16])
++ if have != want {
++ // Look for relocation so we can explain what went wrong.
++ for _, r := range sym.Reloc {
++ if r.Offset == i {
++ t.Errorf("%s: %s+%#x: %s: have %#x want %#x", obj, name, i, r.Sym, have, want)
++ continue Data
++ }
++ }
++ t.Errorf("%s: %s+%#x: have %#x want %#x", obj, name, i, have, want)
++ }
++ }
++ }
++}
+diff --git a/src/cmd/newlink/dead.go b/src/cmd/newlink/dead.go
+new file mode 100644
+index 0000000..ee23a61
+--- /dev/null
++++ b/src/cmd/newlink/dead.go
+@@ -0,0 +1,74 @@
++// Copyright 2014 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++// Removal of dead code and data.
++
++package main
++
++import "cmd/internal/goobj"
++
++// dead removes unreachable code and data from the program.
++// It is basically a mark-sweep garbage collection: traverse all the
++// symbols reachable from the entry (startSymID) and then delete
++// the rest.
++func (p *Prog) dead() {
++ p.Dead = make(map[goobj.SymID]bool)
++ reachable := make(map[goobj.SymID]bool)
++ p.walkDead(p.startSym, reachable)
++
++ for sym := range p.Syms {
++ if !reachable[sym] {
++ delete(p.Syms, sym)
++ p.Dead[sym] = true
++ }
++ }
++
++ for sym := range p.Missing {
++ if !reachable[sym] {
++ delete(p.Missing, sym)
++ p.Dead[sym] = true
++ }
++ }
++
++ p.SymOrder = removeDead(p.SymOrder, reachable)
++
++ for _, pkg := range p.Packages {
++ pkg.Syms = removeDead(pkg.Syms, reachable)
++ }
++}
++
++// walkDead traverses the symbols reachable from sym, adding them to reachable.
++// The caller has verified that reachable[sym] = false.
++func (p *Prog) walkDead(sym goobj.SymID, reachable map[goobj.SymID]bool) {
++ reachable[sym] = true
++ s := p.Syms[sym]
++ if s == nil {
++ return
++ }
++ for i := range s.Reloc {
++ r := &s.Reloc[i]
++ if !reachable[r.Sym] {
++ p.walkDead(r.Sym, reachable)
++ }
++ }
++ if s.Func != nil {
++ for _, fdata := range s.Func.FuncData {
++ if fdata.Sym.Name != "" && !reachable[fdata.Sym] {
++ p.walkDead(fdata.Sym, reachable)
++ }
++ }
++ }
++}
++
++// removeDead removes unreachable (dead) symbols from syms,
++// returning a shortened slice using the same underlying array.
++func removeDead(syms []*Sym, reachable map[goobj.SymID]bool) []*Sym {
++ keep := syms[:0]
++ for _, sym := range syms {
++ if reachable[sym.SymID] {
++ keep = append(keep, sym)
++ }
++ }
++ return keep
++}
+diff --git a/src/cmd/newlink/dead_test.go b/src/cmd/newlink/dead_test.go
+new file mode 100644
+index 0000000..eb34d05
+--- /dev/null
++++ b/src/cmd/newlink/dead_test.go
+@@ -0,0 +1,97 @@
++// Copyright 2014 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++package main
++
++import (
++ "cmd/internal/goobj"
++ "reflect"
++ "strings"
++ "testing"
++)
++
++// Each test case is an object file, generated from a corresponding .s file.
++// The symbols in the object file with a dead_ prefix are the ones that
++// should be removed from the program.
++var deadTests = []string{
++ "testdata/dead.6",
++}
++
++func TestDead(t *testing.T) {
++ for _, obj := range deadTests {
++ p := Prog{GOOS: "darwin", GOARCH: "amd64", StartSym: "start"}
++ p.omitRuntime = true
++ p.Error = func(s string) { t.Error(s) }
++ p.init()
++ p.scan(obj)
++ if p.NumError > 0 {
++ continue // already reported
++ }
++ origSyms := copyMap(p.Syms)
++ origMissing := copyMap(p.Missing)
++ origSymOrder := copySlice(p.SymOrder)
++ origPkgSyms := copySlice(p.Packages["main"].Syms)
++ p.dead()
++ checkDeadMap(t, obj, "p.Syms", origSyms, p.Syms)
++ checkDeadMap(t, obj, "p.Missing", origMissing, p.Missing)
++ checkDeadSlice(t, obj, "p.SymOrder", origSymOrder, p.SymOrder)
++ checkDeadSlice(t, obj, `p.Packages["main"].Syms`, origPkgSyms, p.Packages["main"].Syms)
++ }
++}
++
++func copyMap(m interface{}) interface{} {
++ v := reflect.ValueOf(m)
++ out := reflect.MakeMap(v.Type())
++ for _, key := range v.MapKeys() {
++ out.SetMapIndex(key, v.MapIndex(key))
++ }
++ return out.Interface()
++}
++
++func checkDeadMap(t *testing.T, obj, name string, old, new interface{}) {
++ vold := reflect.ValueOf(old)
++ vnew := reflect.ValueOf(new)
++ for _, vid := range vold.MapKeys() {
++ id := vid.Interface().(goobj.SymID)
++ if strings.HasPrefix(id.Name, "dead_") {
++ if vnew.MapIndex(vid).IsValid() {
++ t.Errorf("%s: %s contains unnecessary symbol %s", obj, name, id)
++ }
++ } else {
++ if !vnew.MapIndex(vid).IsValid() {
++ t.Errorf("%s: %s is missing symbol %s", obj, name, id)
++ }
++ }
++ }
++ for _, vid := range vnew.MapKeys() {
++ id := vid.Interface().(goobj.SymID)
++ if !vold.MapIndex(vid).IsValid() {
++ t.Errorf("%s: %s contains unexpected symbol %s", obj, name, id)
++ }
++ }
++}
++
++func copySlice(x []*Sym) (out []*Sym) {
++ return append(out, x...)
++}
++
++func checkDeadSlice(t *testing.T, obj, name string, old, new []*Sym) {
++ for i, s := range old {
++ if strings.HasPrefix(s.Name, "dead_") {
++ continue
++ }
++ if len(new) == 0 {
++ t.Errorf("%s: %s is missing symbol %s\nhave%v\nwant%v", obj, name, s, new, old[i:])
++ return
++ }
++ if new[0].SymID != s.SymID {
++ t.Errorf("%s: %s is incorrect: have %s, want %s\nhave%v\nwant%v", obj, name, new[0].SymID, s.SymID, new, old[i:])
++ return
++ }
++ new = new[1:]
++ }
++ if len(new) > 0 {
++ t.Errorf("%s: %s has unexpected symbols: %v", obj, name, new)
++ }
++}
+diff --git a/src/cmd/newlink/debug.go b/src/cmd/newlink/debug.go
+new file mode 100644
+index 0000000..ee20644
+--- /dev/null
++++ b/src/cmd/newlink/debug.go
+@@ -0,0 +1,11 @@
++// Copyright 2014 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++// Generation of debug data structures (in the executable but not mapped at run time).
++// See also runtime.go.
++
++package main
++
++func (p *Prog) debug() {
++}
+diff --git a/src/cmd/newlink/hex_test.go b/src/cmd/newlink/hex_test.go
+new file mode 100644
+index 0000000..b76b266
+--- /dev/null
++++ b/src/cmd/newlink/hex_test.go
+@@ -0,0 +1,74 @@
++// Copyright 2014 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++package main
++
++import (
++ "encoding/hex"
++ "fmt"
++ "io/ioutil"
++ "regexp"
++ "strconv"
++ "strings"
++ "testing"
++)
++
++// mustParseHexdumpFile returns a block of data generated by
++// parsing the hex dump in the named file.
++// If the file cannot be read or does not contain a valid hex dump,
++// mustParseHexdumpFile calls t.Fatal.
++func mustParseHexdumpFile(t *testing.T, file string) []byte {
++ hex, err := ioutil.ReadFile(file)
++ if err != nil {
++ t.Fatal(err)
++ }
++ data, err := parseHexdump(string(hex))
++ if err != nil {
++ t.Fatal(err)
++ }
++ return data
++}
++
++// parseHexdump parses the hex dump in text, which should be the
++// output of "hexdump -C" or Plan 9's "xd -b",
++// and returns the original data used to produce the dump.
++// It is meant to enable storing golden binary files as text, so that
++// changes to the golden files can be seen during code reviews.
++func parseHexdump(text string) ([]byte, error) {
++ var out []byte
++ for _, line := range strings.Split(text, "\n") {
++ if i := strings.Index(line, "|"); i >= 0 { // remove text dump
++ line = line[:i]
++ }
++ f := strings.Fields(line)
++ if len(f) > 1+16 {
++ return nil, fmt.Errorf("parsing hex dump: too many fields on line %q", line)
++ }
++ if len(f) == 0 || len(f) == 1 && f[0] == "*" { // all zeros block omitted
++ continue
++ }
++ addr64, err := strconv.ParseUint(f[0], 16, 0)
++ if err != nil {
++ return nil, fmt.Errorf("parsing hex dump: invalid address %q", f[0])
++ }
++ addr := int(addr64)
++ if len(out) < addr {
++ out = append(out, make([]byte, addr-len(out))...)
++ }
++ for _, x := range f[1:] {
++ val, err := strconv.ParseUint(x, 16, 8)
++ if err != nil {
++ return nil, fmt.Errorf("parsing hexdump: invalid hex byte %q", x)
++ }
++ out = append(out, byte(val))
++ }
++ }
++ return out, nil
++}
++
++func hexdump(data []byte) string {
++ text := hex.Dump(data) + fmt.Sprintf("%08x\n", len(data))
++ text = regexp.MustCompile(`\n([0-9a-f]+(\s+00){16}.*\n)+`).ReplaceAllString(text, "\n*\n")
++ return text
++}
+diff --git a/src/cmd/newlink/layout.go b/src/cmd/newlink/layout.go
+new file mode 100644
+index 0000000..d5c291e
+--- /dev/null
++++ b/src/cmd/newlink/layout.go
+@@ -0,0 +1,180 @@
++// Copyright 2014 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++// Executable image layout - address assignment.
++
++package main
++
++import (
++ "cmd/internal/goobj"
++)
++
++// A layoutSection describes a single section to add to the
++// final executable. Go binaries only have a fixed set of possible
++// sections, and the symbol kind determines the section.
++type layoutSection struct {
++ Segment string
++ Section string
++ Kind goobj.SymKind
++ Index int
++}
++
++// layout defines the layout of the generated Go executable.
++// The order of entries here is the order in the executable.
++// Entries with the same Segment name must be contiguous.
++var layout = []layoutSection{
++ {Segment: "text", Section: "text", Kind: goobj.STEXT},
++ {Segment: "rodata", Section: "rodata", Kind: goobj.SRODATA},
++ {Segment: "rodata", Section: "functab", Kind: goobj.SPCLNTAB},
++ {Segment: "rodata", Section: "typelink", Kind: goobj.STYPELINK},
++ {Segment: "data", Section: "noptrdata", Kind: goobj.SNOPTRDATA},
++ {Segment: "data", Section: "data", Kind: goobj.SDATA},
++ {Segment: "data", Section: "bss", Kind: goobj.SBSS},
++ {Segment: "data", Section: "noptrbss", Kind: goobj.SNOPTRBSS},
++
++ // Later:
++ // {"rodata", "type", goobj.STYPE},
++ // {"rodata", "string", goobj.SSTRING},
++ // {"rodata", "gostring", goobj.SGOSTRING},
++ // {"rodata", "gofunc", goobj.SGOFUNC},
++}
++
++// layoutByKind maps from SymKind to an entry in layout.
++var layoutByKind []*layoutSection
++
++func init() {
++ // Build index from symbol type to layout entry.
++ max := 0
++ for _, sect := range layout {
++ if max <= int(sect.Kind) {
++ max = int(sect.Kind) + 1
++ }
++ }
++ layoutByKind = make([]*layoutSection, max)
++ for i := range layout {
++ sect := &layout[i]
++ layoutByKind[sect.Kind] = sect
++ sect.Index = i
++ }
++}
++
++// layout arranges symbols into sections and sections into segments,
++// and then it assigns addresses to segments, sections, and symbols.
++func (p *Prog) layout() {
++ sections := make([]*Section, len(layout))
++
++ // Assign symbols to sections using index, creating sections as needed.
++ // Could keep sections separated by type during input instead.
++ for _, sym := range p.SymOrder {
++ kind := sym.Kind
++ if kind < 0 || int(kind) >= len(layoutByKind) || layoutByKind[kind] == nil {
++ p.errorf("%s: unexpected symbol kind %v", sym.SymID, kind)
++ continue
++ }
++ lsect := layoutByKind[kind]
++ sect := sections[lsect.Index]
++ if sect == nil {
++ sect = &Section{
++ Name: lsect.Section,
++ Align: 1,
++ }
++ sections[lsect.Index] = sect
++ }
++ if sym.Data.Size > 0 || len(sym.Bytes) > 0 {
++ sect.InFile = true
++ }
++ sym.Section = sect
++ sect.Syms = append(sect.Syms, sym)
++
++ // TODO(rsc): Incorporate alignment information.
++ // First that information needs to be added to the object files.
++ //
++ // if sect.Align < Addr(sym.Align) {
++ // sect.Align = Addr(sym.Align)
++ // }
++ }
++
++ // Assign sections to segments, creating segments as needed.
++ var seg *Segment
++ for i, sect := range sections {
++ if sect == nil {
++ continue
++ }
++ segName := layout[i].Segment
++
++ // Special case: Mach-O does not support "rodata" segment,
++ // so store read-only data in text segment.
++ if p.GOOS == "darwin" && segName == "rodata" {
++ segName = "text"
++ }
++
++ if seg == nil || seg.Name != segName {
++ seg = &Segment{
++ Name: segName,
++ }
++ p.Segments = append(p.Segments, seg)
++ }
++ sect.Segment = seg
++ seg.Sections = append(seg.Sections, sect)
++ }
++
++ // Assign addresses.
++
++ // TODO(rsc): This choice needs to be informed by both
++ // the formatter and the target architecture.
++ // And maybe eventually a command line flag (sigh).
++ const segAlign = 4096
++
++ // TODO(rsc): Use a larger amount on most systems, which will let the
++ // compiler eliminate more nil checks.
++ if p.UnmappedSize == 0 {
++ p.UnmappedSize = segAlign
++ }
++
++ // TODO(rsc): addr := Addr(0) when generating a shared library or PIE.
++ addr := p.UnmappedSize
++
++ // Account for initial file header.
++ hdrVirt, hdrFile := p.formatter.headerSize(p)
++ addr += hdrVirt
++
++ // Assign addresses to segments, sections, symbols.
++ // Assign sizes to segments, sections.
++ startVirt := addr
++ startFile := hdrFile
++ for _, seg := range p.Segments {
++ addr = round(addr, segAlign)
++ seg.VirtAddr = addr
++ seg.FileOffset = startFile + seg.VirtAddr - startVirt
++ for _, sect := range seg.Sections {
++ addr = round(addr, sect.Align)
++ sect.VirtAddr = addr
++ for _, sym := range sect.Syms {
++ // TODO(rsc): Respect alignment once we have that information.
++ sym.Addr = addr
++ addr += Addr(sym.Size)
++ }
++ sect.Size = addr - sect.VirtAddr
++ if sect.InFile {
++ seg.FileSize = addr - seg.VirtAddr
++ }
++ }
++ seg.VirtSize = addr - seg.VirtAddr
++ }
++
++ // Define symbols for section names.
++ var progEnd Addr
++ for i, sect := range sections {
++ name := layout[i].Section
++ var start, end Addr
++ if sect != nil {
++ start = sect.VirtAddr
++ end = sect.VirtAddr + sect.Size
++ }
++ p.defineConst("runtime."+name, start)
++ p.defineConst("runtime.e"+name, end)
++ progEnd = end
++ }
++ p.defineConst("runtime.end", progEnd)
++}
+diff --git a/src/cmd/newlink/layout_test.go b/src/cmd/newlink/layout_test.go
+new file mode 100644
+index 0000000..e5513af
+--- /dev/null
++++ b/src/cmd/newlink/layout_test.go
+@@ -0,0 +1,45 @@
++// Copyright 2014 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++package main
++
++import (
++ "bytes"
++ "strings"
++ "testing"
++)
++
++func TestLayout(t *testing.T) {
++ p := Prog{GOOS: "darwin", GOARCH: "amd64", StartSym: "text_start"}
++ p.omitRuntime = true
++ p.Error = func(s string) { t.Error(s) }
++ var buf bytes.Buffer
++ const obj = "testdata/layout.6"
++ p.link(&buf, obj)
++ if p.NumError > 0 {
++ return // already reported
++ }
++ if len(p.Dead) > 0 {
++ t.Errorf("%s: unexpected dead symbols %v", obj, p.Dead)
++ return
++ }
++
++ for _, sym := range p.SymOrder {
++ if p.isAuto(sym.SymID) {
++ continue
++ }
++ if sym.Section == nil {
++ t.Errorf("%s: symbol %s is missing section", obj, sym)
++ continue
++ }
++ i := strings.Index(sym.Name, "_")
++ if i < 0 {
++ t.Errorf("%s: unexpected symbol %s", obj, sym)
++ continue
++ }
++ if sym.Section.Name != sym.Name[:i] {
++ t.Errorf("%s: symbol %s in section %s, want %s", obj, sym, sym.Section.Name, sym.Name[:i])
++ }
++ }
++}
+diff --git a/src/cmd/newlink/link_test.go b/src/cmd/newlink/link_test.go
+new file mode 100644
+index 0000000..b5ae15f
+--- /dev/null
++++ b/src/cmd/newlink/link_test.go
+@@ -0,0 +1,35 @@
++// Copyright 2014 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++package main
++
++import (
++ "bytes"
++ "cmd/internal/goobj"
++ "io/ioutil"
++ "testing"
++)
++
++func TestLinkHello(t *testing.T) {
++ p := &Prog{
++ GOOS: "darwin",
++ GOARCH: "amd64",
++ Error: func(s string) { t.Error(s) },
++ StartSym: "_rt0_go",
++ }
++ var buf bytes.Buffer
++ p.link(&buf, "testdata/hello.6")
++ if p.NumError > 0 {
++ return
++ }
++ if p.Syms[goobj.SymID{"_rt0_go", 0}] == nil || p.Syms[goobj.SymID{"hello", 1}] == nil {
++ t.Errorf("Syms = %v, want at least [_rt0_go hello<1>]", p.Syms)
++ }
++
++ // uncomment to leave file behind for execution:
++ if false {
++ ioutil.WriteFile("a.out", buf.Bytes(), 0777)
++ }
++ checkGolden(t, buf.Bytes(), "testdata/link.hello.darwin.amd64")
++}
+diff --git a/src/cmd/newlink/load.go b/src/cmd/newlink/load.go
+new file mode 100644
+index 0000000..50602b8
+--- /dev/null
++++ b/src/cmd/newlink/load.go
+@@ -0,0 +1,108 @@
++// Copyright 2014 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++// Loading of code and data fragments from package files into final image.
++
++package main
++
++import (
++ "cmd/internal/obj"
++ "os"
++)
++
++// load allocates segment images, populates them with data
++// read from package files, and applies relocations to the data.
++func (p *Prog) load() {
++ // TODO(rsc): mmap the output file and store the data directly.
++ // That will make writing the output file more efficient.
++ for _, seg := range p.Segments {
++ seg.Data = make([]byte, seg.FileSize)
++ }
++ for _, pkg := range p.Packages {
++ p.loadPackage(pkg)
++ }
++}
++
++// loadPackage loads and relocates data for all the
++// symbols needed in the given package.
++func (p *Prog) loadPackage(pkg *Package) {
++ if pkg.File == "" {
++ // This "package" contains internally generated symbols only.
++ // All such symbols have a sym.Bytes field holding the actual data
++ // (if any), plus relocations.
++ for _, sym := range pkg.Syms {
++ if sym.Bytes == nil {
++ continue
++ }
++ seg := sym.Section.Segment
++ off := sym.Addr - seg.VirtAddr
++ data := seg.Data[off : off+Addr(sym.Size)]
++ copy(data, sym.Bytes)
++ p.relocateSym(sym, data)
++ }
++ return
++ }
++
++ // Package stored in file.
++ f, err := os.Open(pkg.File)
++ if err != nil {
++ p.errorf("%v", err)
++ return
++ }
++ defer f.Close()
++
++ // TODO(rsc): Mmap file into memory.
++
++ for _, sym := range pkg.Syms {
++ if sym.Data.Size == 0 {
++ continue
++ }
++ // TODO(rsc): If not using mmap, at least coalesce nearby reads.
++ if sym.Section == nil {
++ p.errorf("internal error: missing section for %s", sym.Name)
++ }
++ seg := sym.Section.Segment
++ off := sym.Addr - seg.VirtAddr
++ if off >= Addr(len(seg.Data)) || off+Addr(sym.Data.Size) > Addr(len(seg.Data)) {
++ p.errorf("internal error: allocated space for %s too small: %d bytes for %d+%d (%d)", sym, len(seg.Data), off, sym.Data.Size, sym.Size)
++ }
++ data := seg.Data[off : off+Addr(sym.Data.Size)]
++ _, err := f.ReadAt(data, sym.Data.Offset)
++ if err != nil {
++ p.errorf("reading %v: %v", sym.SymID, err)
++ }
++ p.relocateSym(sym, data)
++ }
++}
++
++// relocateSym applies relocations to sym's data.
++func (p *Prog) relocateSym(sym *Sym, data []byte) {
++ for i := range sym.Reloc {
++ r := &sym.Reloc[i]
++ targ := p.Syms[r.Sym]
++ if targ == nil {
++ p.errorf("%v: reference to undefined symbol %v", sym, r.Sym)
++ continue
++ }
++ val := targ.Addr + Addr(r.Add)
++ switch r.Type {
++ default:
++ p.errorf("%v: unknown relocation type %d", sym, r.Type)
++ case obj.R_ADDR, obj.R_CALLIND:
++ // ok
++ case obj.R_PCREL, obj.R_CALL:
++ val -= sym.Addr + Addr(r.Offset+r.Size)
++ }
++ frag := data[r.Offset : r.Offset+r.Size]
++ switch r.Size {
++ default:
++ p.errorf("%v: unknown relocation size %d", sym, r.Size)
++ case 4:
++ // TODO(rsc): Check for overflow?
++ p.byteorder.PutUint32(frag, uint32(val))
++ case 8:
++ p.byteorder.PutUint64(frag, uint64(val))
++ }
++ }
++}
+diff --git a/src/cmd/newlink/macho.go b/src/cmd/newlink/macho.go
+new file mode 100644
+index 0000000..4e5524b
+--- /dev/null
++++ b/src/cmd/newlink/macho.go
+@@ -0,0 +1,380 @@
++// Copyright 2014 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++// Mach-O (Darwin) object file writing.
++
++package main
++
++import (
++ "debug/macho"
++ "encoding/binary"
++ "io"
++ "strings"
++)
++
++// machoFormat is the implementation of formatter.
++type machoFormat struct{}
++
++// machoHeader and friends are data structures
++// corresponding to the Mach-O file header
++// to be written to disk.
++
++const (
++ macho64Bit = 1 << 24
++ machoSubCPU386 = 3
++)
++
++// machoArch describes a Mach-O target architecture.
++type machoArch struct {
++ CPU uint32
++ SubCPU uint32
++}
++
++// machoHeader is the Mach-O file header.
++type machoHeader struct {
++ machoArch
++ FileType uint32
++ Loads []*machoLoad
++ Segments []*machoSegment
++ p *Prog // for reporting errors
++}
++
++// machoLoad is a Mach-O load command.
++type machoLoad struct {
++ Type uint32
++ Data []uint32
++}
++
++// machoSegment is a Mach-O segment.
++type machoSegment struct {
++ Name string
++ VirtAddr Addr
++ VirtSize Addr
++ FileOffset Addr
++ FileSize Addr
++ Prot1 uint32
++ Prot2 uint32
++ Flags uint32
++ Sections []*machoSection
++}
++
++// machoSection is a Mach-O section, inside a segment.
++type machoSection struct {
++ Name string
++ Segment string
++ Addr Addr
++ Size Addr
++ Offset uint32
++ Align uint32
++ Reloc uint32
++ Nreloc uint32
++ Flags uint32
++ Res1 uint32
++ Res2 uint32
++}
++
++// layout positions the segments and sections in p
++// to make room for the Mach-O file header.
++// That is, it edits their VirtAddr fields to adjust for the presence
++// of the Mach-O header at the beginning of the address space.
++func (machoFormat) headerSize(p *Prog) (virt, file Addr) {
++ var h machoHeader
++ h.init(p)
++ size := Addr(h.size())
++ size = round(size, 4096)
++ p.HeaderSize = size
++ return size, size
++}
++
++// write writes p to w as a Mach-O executable.
++// layout(p) must have already been called,
++// and the number, sizes, and addresses of the segments
++// and sections must not have been modified since the call.
++func (machoFormat) write(w io.Writer, p *Prog) {
++ var h machoHeader
++ h.init(p)
++ off := Addr(0)
++ enc := h.encode()
++ w.Write(enc)
++ off += Addr(len(enc))
++ for _, seg := range p.Segments {
++ if seg.FileOffset < off {
++ h.p.errorf("mach-o error: invalid file offset")
++ }
++ w.Write(make([]byte, int(seg.FileOffset-off)))
++ if seg.FileSize != Addr(len(seg.Data)) {
++ h.p.errorf("mach-o error: invalid file size")
++ }
++ w.Write(seg.Data)
++ off = seg.FileOffset + Addr(len(seg.Data))
++ }
++}
++
++// Conversion of Prog to macho data structures.
++
++// machoArches maps from GOARCH to machoArch.
++var machoArches = map[string]machoArch{
++ "amd64": {
++ CPU: uint32(macho.CpuAmd64),
++ SubCPU: uint32(machoSubCPU386),
++ },
++}
++
++// init initializes the header h to describe p.
++func (h *machoHeader) init(p *Prog) {
++ h.p = p
++ h.Segments = nil
++ h.Loads = nil
++ var ok bool
++ h.machoArch, ok = machoArches[p.GOARCH]
++ if !ok {
++ p.errorf("mach-o: unknown target GOARCH %q", p.GOARCH)
++ return
++ }
++ h.FileType = uint32(macho.TypeExec)
++
++ mseg := h.addSegment(p, "__PAGEZERO", nil)
++ mseg.VirtSize = p.UnmappedSize
++
++ for _, seg := range p.Segments {
++ h.addSegment(p, "__"+strings.ToUpper(seg.Name), seg)
++ }
++
++ var data []uint32
++ switch h.CPU {
++ default:
++ p.errorf("mach-o: unknown cpu %#x for GOARCH %q", h.CPU, p.GOARCH)
++ case uint32(macho.CpuAmd64):
++ data = make([]uint32, 2+42)
++ data[0] = 4 // thread type
++ data[1] = 42 // word count
++ data[2+32] = uint32(p.Entry) // RIP register, in two parts
++ data[2+32+1] = uint32(p.Entry >> 32)
++ }
++
++ h.Loads = append(h.Loads, &machoLoad{
++ Type: uint32(macho.LoadCmdUnixThread),
++ Data: data,
++ })
++}
++
++// addSegment adds to h a Mach-O segment like seg with the given name.
++func (h *machoHeader) addSegment(p *Prog, name string, seg *Segment) *machoSegment {
++ mseg := &machoSegment{
++ Name: name,
++ }
++ h.Segments = append(h.Segments, mseg)
++ if seg == nil {
++ return mseg
++ }
++
++ mseg.VirtAddr = seg.VirtAddr
++ mseg.VirtSize = seg.VirtSize
++ mseg.FileOffset = round(seg.FileOffset, 4096)
++ mseg.FileSize = seg.FileSize
++
++ if name == "__TEXT" {
++ // Initially RWX, then just RX
++ mseg.Prot1 = 7
++ mseg.Prot2 = 5
++
++ // Text segment maps Mach-O header, needed by dynamic linker.
++ mseg.VirtAddr -= p.HeaderSize
++ mseg.VirtSize += p.HeaderSize
++ mseg.FileOffset -= p.HeaderSize
++ mseg.FileSize += p.HeaderSize
++ } else {
++ // RW
++ mseg.Prot1 = 3
++ mseg.Prot2 = 3
++ }
++
++ for _, sect := range seg.Sections {
++ h.addSection(mseg, seg, sect)
++ }
++ return mseg
++}
++
++// addSection adds to mseg a Mach-O section like sect, inside seg, with the given name.
++func (h *machoHeader) addSection(mseg *machoSegment, seg *Segment, sect *Section) {
++ msect := &machoSection{
++ Name: "__" + sect.Name,
++ Segment: mseg.Name,
++ // Reloc: sect.RelocOffset,
++ // NumReloc: sect.RelocLen / 8,
++ Addr: sect.VirtAddr,
++ Size: sect.Size,
++ }
++ mseg.Sections = append(mseg.Sections, msect)
++
++ for 1<<msect.Align < sect.Align {
++ msect.Align++
++ }
++
++ if off := sect.VirtAddr - seg.VirtAddr; off < seg.FileSize {
++ // Data in file.
++ if sect.Size > seg.FileSize-off {
++ h.p.errorf("mach-o error: section crosses file boundary")
++ }
++ msect.Offset = uint32(seg.FileOffset + off)
++ } else {
++ // Zero filled.
++ msect.Flags |= 1
++ }
++
++ if sect.Name == "text" {
++ msect.Flags |= 0x400 // contains executable instructions
++ }
++}
++
++// A machoWriter helps write Mach-O headers.
++// It is basically a buffer with some helper routines for writing integers.
++type machoWriter struct {
++ dst []byte
++ tmp [8]byte
++ order binary.ByteOrder
++ is64 bool
++ p *Prog
++}
++
++// if64 returns x if w is writing a 64-bit object file; otherwise it returns y.
++func (w *machoWriter) if64(x, y interface{}) interface{} {
++ if w.is64 {
++ return x
++ }
++ return y
++}
++
++// encode encodes each of the given arguments into the writer.
++// It encodes uint32, []uint32, uint64, and []uint64 by writing each value
++// in turn in the correct byte order for the output file.
++// It encodes an Addr as a uint64 if writing a 64-bit output file, or else as a uint32.
++// It encodes []byte and string by writing the raw bytes (no length prefix).
++// It skips nil values in the args list.
++func (w *machoWriter) encode(args ...interface{}) {
++ for _, arg := range args {
++ switch arg := arg.(type) {
++ default:
++ w.p.errorf("mach-o error: cannot encode %T", arg)
++ case nil:
++ // skip
++ case []byte:
++ w.dst = append(w.dst, arg...)
++ case string:
++ w.dst = append(w.dst, arg...)
++ case uint32:
++ w.order.PutUint32(w.tmp[:], arg)
++ w.dst = append(w.dst, w.tmp[:4]...)
++ case []uint32:
++ for _, x := range arg {
++ w.order.PutUint32(w.tmp[:], x)
++ w.dst = append(w.dst, w.tmp[:4]...)
++ }
++ case uint64:
++ w.order.PutUint64(w.tmp[:], arg)
++ w.dst = append(w.dst, w.tmp[:8]...)
++ case Addr:
++ if w.is64 {
++ w.order.PutUint64(w.tmp[:], uint64(arg))
++ w.dst = append(w.dst, w.tmp[:8]...)
++ } else {
++ if Addr(uint32(arg)) != arg {
++ w.p.errorf("mach-o error: truncating address %#x to uint32", arg)
++ }
++ w.order.PutUint32(w.tmp[:], uint32(arg))
++ w.dst = append(w.dst, w.tmp[:4]...)
++ }
++ }
++ }
++}
++
++// segmentSize returns the size of the encoding of seg in bytes.
++func (w *machoWriter) segmentSize(seg *machoSegment) int {
++ if w.is64 {
++ return 18*4 + 20*4*len(seg.Sections)
++ }
++ return 14*4 + 22*4*len(seg.Sections)
++}
++
++// zeroPad returns the string s truncated or padded with NULs to n bytes.
++func zeroPad(s string, n int) string {
++ if len(s) >= n {
++ return s[:n]
++ }
++ return s + strings.Repeat("\x00", n-len(s))
++}
++
++// size returns the encoded size of the header.
++func (h *machoHeader) size() int {
++ // Could write separate code, but encoding is cheap; encode and throw it away.
++ return len(h.encode())
++}
++
++// encode returns the Mach-O encoding of the header.
++func (h *machoHeader) encode() []byte {
++ w := &machoWriter{p: h.p}
++ w.is64 = h.CPU&macho64Bit != 0
++ w.order = w.p.byteorder
++
++ loadSize := 0
++ for _, seg := range h.Segments {
++ loadSize += w.segmentSize(seg)
++ }
++ for _, l := range h.Loads {
++ loadSize += 4 * (2 + len(l.Data))
++ }
++
++ w.encode(
++ w.if64(macho.Magic64, macho.Magic32),
++ uint32(h.CPU),
++ uint32(h.SubCPU),
++ uint32(h.FileType),
++ uint32(len(h.Loads)+len(h.Segments)),
++ uint32(loadSize),
++ uint32(1),
++ w.if64(uint32(0), nil),
++ )
++
++ for _, seg := range h.Segments {
++ w.encode(
++ w.if64(uint32(macho.LoadCmdSegment64), uint32(macho.LoadCmdSegment)),
++ uint32(w.segmentSize(seg)),
++ zeroPad(seg.Name, 16),
++ seg.VirtAddr,
++ seg.VirtSize,
++ seg.FileOffset,
++ seg.FileSize,
++ seg.Prot1,
++ seg.Prot2,
++ uint32(len(seg.Sections)),
++ seg.Flags,
++ )
++ for _, sect := range seg.Sections {
++ w.encode(
++ zeroPad(sect.Name, 16),
++ zeroPad(seg.Name, 16),
++ sect.Addr,
++ sect.Size,
++ sect.Offset,
++ sect.Align,
++ sect.Reloc,
++ sect.Nreloc,
++ sect.Flags,
++ sect.Res1,
++ sect.Res2,
++ w.if64(uint32(0), nil),
++ )
++ }
++ }
++
++ for _, load := range h.Loads {
++ w.encode(
++ load.Type,
++ uint32(4*(2+len(load.Data))),
++ load.Data,
++ )
++ }
++
++ return w.dst
++}
+diff --git a/src/cmd/newlink/macho_test.go b/src/cmd/newlink/macho_test.go
+new file mode 100644
+index 0000000..37c4418
+--- /dev/null
++++ b/src/cmd/newlink/macho_test.go
+@@ -0,0 +1,407 @@
++// Copyright 2014 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++package main
++
++import (
++ "bytes"
++ "debug/macho"
++ "encoding/binary"
++ "fmt"
++ "io/ioutil"
++ "strings"
++ "testing"
++)
++
++// Test macho writing by checking that each generated prog can be written
++// and then read back using debug/macho to get the same prog.
++// Also check against golden testdata file.
++var machoWriteTests = []struct {
++ name string
++ golden bool
++ prog *Prog
++}{
++ // amd64 exit 9
++ {
++ name: "exit9",
++ golden: true,
++ prog: &Prog{
++ GOARCH: "amd64",
++ GOOS: "darwin",
++ UnmappedSize: 0x1000,
++ Entry: 0x1000,
++ Segments: []*Segment{
++ {
++ Name: "text",
++ VirtAddr: 0x1000,
++ VirtSize: 13,
++ FileOffset: 0,
++ FileSize: 13,
++ Data: []byte{
++ 0xb8, 0x01, 0x00, 0x00, 0x02, // MOVL $0x2000001, AX
++ 0xbf, 0x09, 0x00, 0x00, 0x00, // MOVL $9, DI
++ 0x0f, 0x05, // SYSCALL
++ 0xf4, // HLT
++ },
++ Sections: []*Section{
++ {
++ Name: "text",
++ VirtAddr: 0x1000,
++ Size: 13,
++ Align: 64,
++ },
++ },
++ },
++ },
++ },
++ },
++
++ // amd64 write hello world & exit 9
++ {
++ name: "hello",
++ golden: true,
++ prog: &Prog{
++ GOARCH: "amd64",
++ GOOS: "darwin",
++ UnmappedSize: 0x1000,
++ Entry: 0x1000,
++ Segments: []*Segment{
++ {
++ Name: "text",
++ VirtAddr: 0x1000,
++ VirtSize: 35,
++ FileOffset: 0,
++ FileSize: 35,
++ Data: []byte{
++ 0xb8, 0x04, 0x00, 0x00, 0x02, // MOVL $0x2000001, AX
++ 0xbf, 0x01, 0x00, 0x00, 0x00, // MOVL $1, DI
++ 0xbe, 0x00, 0x30, 0x00, 0x00, // MOVL $0x3000, SI
++ 0xba, 0x0c, 0x00, 0x00, 0x00, // MOVL $12, DX
++ 0x0f, 0x05, // SYSCALL
++ 0xb8, 0x01, 0x00, 0x00, 0x02, // MOVL $0x2000001, AX
++ 0xbf, 0x09, 0x00, 0x00, 0x00, // MOVL $9, DI
++ 0x0f, 0x05, // SYSCALL
++ 0xf4, // HLT
++ },
++ Sections: []*Section{
++ {
++ Name: "text",
++ VirtAddr: 0x1000,
++ Size: 35,
++ Align: 64,
++ },
++ },
++ },
++ {
++ Name: "data",
++ VirtAddr: 0x2000,
++ VirtSize: 12,
++ FileOffset: 0x1000,
++ FileSize: 12,
++ Data: []byte("hello world\n"),
++ Sections: []*Section{
++ {
++ Name: "data",
++ VirtAddr: 0x2000,
++ Size: 12,
++ Align: 64,
++ },
++ },
++ },
++ },
++ },
++ },
++
++ // amd64 write hello world from rodata & exit 0
++ {
++ name: "helloro",
++ golden: true,
++ prog: &Prog{
++ GOARCH: "amd64",
++ GOOS: "darwin",
++ UnmappedSize: 0x1000,
++ Entry: 0x1000,
++ Segments: []*Segment{
++ {
++ Name: "text",
++ VirtAddr: 0x1000,
++ VirtSize: 0x100c,
++ FileOffset: 0,
++ FileSize: 0x100c,
++ Data: concat(
++ []byte{
++ 0xb8, 0x04, 0x00, 0x00, 0x02, // MOVL $0x2000001, AX
++ 0xbf, 0x01, 0x00, 0x00, 0x00, // MOVL $1, DI
++ 0xbe, 0x00, 0x30, 0x00, 0x00, // MOVL $0x3000, SI
++ 0xba, 0x0c, 0x00, 0x00, 0x00, // MOVL $12, DX
++ 0x0f, 0x05, // SYSCALL
++ 0xb8, 0x01, 0x00, 0x00, 0x02, // MOVL $0x2000001, AX
++ 0xbf, 0x00, 0x00, 0x00, 0x00, // MOVL $0, DI
++ 0x0f, 0x05, // SYSCALL
++ 0xf4, // HLT
++ },
++ make([]byte, 0x1000-35),
++ []byte("hello world\n"),
++ ),
++ Sections: []*Section{
++ {
++ Name: "text",
++ VirtAddr: 0x1000,
++ Size: 35,
++ Align: 64,
++ },
++ {
++ Name: "rodata",
++ VirtAddr: 0x2000,
++ Size: 12,
++ Align: 64,
++ },
++ },
++ },
++ },
++ },
++ },
++}
++
++func concat(xs ...[]byte) []byte {
++ var out []byte
++ for _, x := range xs {
++ out = append(out, x...)
++ }
++ return out
++}
++
++func TestMachoWrite(t *testing.T) {
++ for _, tt := range machoWriteTests {
++ name := tt.prog.GOARCH + "." + tt.name
++ prog := cloneProg(tt.prog)
++ prog.init()
++ var f machoFormat
++ vsize, fsize := f.headerSize(prog)
++ shiftProg(prog, vsize, fsize)
++ var buf bytes.Buffer
++ f.write(&buf, prog)
++ if false { // enable to debug
++ ioutil.WriteFile("a.out", buf.Bytes(), 0777)
++ }
++ read, err := machoRead(machoArches[tt.prog.GOARCH], buf.Bytes())
++ if err != nil {
++ t.Errorf("%s: reading mach-o output:\n\t%v", name, err)
++ continue
++ }
++ diffs := diffProg(read, prog)
++ if diffs != nil {
++ t.Errorf("%s: mismatched prog:\n\t%s", name, strings.Join(diffs, "\n\t"))
++ continue
++ }
++ if !tt.golden {
++ continue
++ }
++ checkGolden(t, buf.Bytes(), "testdata/macho."+name)
++ }
++}
++
++// machoRead reads the mach-o file in data and returns a corresponding prog.
++func machoRead(arch machoArch, data []byte) (*Prog, error) {
++ f, err := macho.NewFile(bytes.NewReader(data))
++ if err != nil {
++ return nil, err
++ }
++
++ var errors []string
++ errorf := func(format string, args ...interface{}) {
++ errors = append(errors, fmt.Sprintf(format, args...))
++ }
++
++ magic := uint32(0xFEEDFACE)
++ if arch.CPU&macho64Bit != 0 {
++ magic |= 1
++ }
++ if f.Magic != magic {
++ errorf("header: Magic = %#x, want %#x", f.Magic, magic)
++ }
++ if f.Cpu != macho.CpuAmd64 {
++ errorf("header: CPU = %#x, want %#x", f.Cpu, macho.CpuAmd64)
++ }
++ if f.SubCpu != 3 {
++ errorf("header: SubCPU = %#x, want %#x", f.SubCpu, 3)
++ }
++ if f.Type != 2 {
++ errorf("header: FileType = %d, want %d", f.Type, 2)
++ }
++ if f.Flags != 1 {
++ errorf("header: Flags = %d, want %d", f.Flags, 1)
++ }
++
++ msects := f.Sections
++ var limit uint64
++ prog := new(Prog)
++ for _, load := range f.Loads {
++ switch load := load.(type) {
++ default:
++ errorf("unexpected macho load %T %x", load, load.Raw())
++
++ case macho.LoadBytes:
++ if len(load) < 8 || len(load)%4 != 0 {
++ errorf("unexpected load length %d", len(load))
++ continue
++ }
++ cmd := f.ByteOrder.Uint32(load)
++ switch macho.LoadCmd(cmd) {
++ default:
++ errorf("unexpected macho load cmd %s", macho.LoadCmd(cmd))
++ case macho.LoadCmdUnixThread:
++ data := make([]uint32, len(load[8:])/4)
++ binary.Read(bytes.NewReader(load[8:]), f.ByteOrder, data)
++ if len(data) != 44 {
++ errorf("macho thread len(data) = %d, want 42", len(data))
++ continue
++ }
++ if data[0] != 4 {
++ errorf("macho thread type = %d, want 4", data[0])
++ }
++ if data[1] != uint32(len(data))-2 {
++ errorf("macho thread desc len = %d, want %d", data[1], uint32(len(data))-2)
++ continue
++ }
++ for i, val := range data[2:] {
++ switch i {
++ default:
++ if val != 0 {
++ errorf("macho thread data[%d] = %#x, want 0", i, val)
++ }
++ case 32:
++ prog.Entry = Addr(val)
++ case 33:
++ prog.Entry |= Addr(val) << 32
++ }
++ }
++ }
++
++ case *macho.Segment:
++ if load.Addr < limit {
++ errorf("segments out of order: %q at %#x after %#x", load.Name, load.Addr, limit)
++ }
++ limit = load.Addr + load.Memsz
++ if load.Name == "__PAGEZERO" || load.Addr == 0 && load.Filesz == 0 {
++ if load.Name != "__PAGEZERO" {
++ errorf("segment with Addr=0, Filesz=0 is named %q, want %q", load.Name, "__PAGEZERO")
++ } else if load.Addr != 0 || load.Filesz != 0 {
++ errorf("segment %q has Addr=%#x, Filesz=%d, want Addr=%#x, Filesz=%d", load.Name, load.Addr, load.Filesz, 0, 0)
++ }
++ prog.UnmappedSize = Addr(load.Memsz)
++ continue
++ }
++
++ if !strings.HasPrefix(load.Name, "__") {
++ errorf("segment name %q does not begin with %q", load.Name, "__")
++ }
++ if strings.ToUpper(load.Name) != load.Name {
++ errorf("segment name %q is not all upper case", load.Name)
++ }
++
++ seg := &Segment{
++ Name: strings.ToLower(strings.TrimPrefix(load.Name, "__")),
++ VirtAddr: Addr(load.Addr),
++ VirtSize: Addr(load.Memsz),
++ FileOffset: Addr(load.Offset),
++ FileSize: Addr(load.Filesz),
++ }
++ prog.Segments = append(prog.Segments, seg)
++
++ data, err := load.Data()
++ if err != nil {
++ errorf("loading data from %q: %v", load.Name, err)
++ }
++ seg.Data = data
++
++ var maxprot, prot uint32
++ if load.Name == "__TEXT" {
++ maxprot, prot = 7, 5
++ } else {
++ maxprot, prot = 3, 3
++ }
++ if load.Maxprot != maxprot || load.Prot != prot {
++ errorf("segment %q protection is %d, %d, want %d, %d",
++ load.Name, load.Maxprot, load.Prot, maxprot, prot)
++ }
++
++ for len(msects) > 0 && msects[0].Addr < load.Addr+load.Memsz {
++ msect := msects[0]
++ msects = msects[1:]
++
++ if msect.Offset > 0 && prog.HeaderSize == 0 {
++ prog.HeaderSize = Addr(msect.Offset)
++ if seg.FileOffset != 0 {
++ errorf("initial segment %q does not map header", load.Name)
++ }
++ seg.VirtAddr += prog.HeaderSize
++ seg.VirtSize -= prog.HeaderSize
++ seg.FileOffset += prog.HeaderSize
++ seg.FileSize -= prog.HeaderSize
++ seg.Data = seg.Data[prog.HeaderSize:]
++ }
++
++ if msect.Addr < load.Addr {
++ errorf("section %q at address %#x is missing segment", msect.Name, msect.Addr)
++ continue
++ }
++
++ if !strings.HasPrefix(msect.Name, "__") {
++ errorf("section name %q does not begin with %q", msect.Name, "__")
++ }
++ if strings.ToLower(msect.Name) != msect.Name {
++ errorf("section name %q is not all lower case", msect.Name)
++ }
++ if msect.Seg != load.Name {
++ errorf("section %q is lists segment name %q, want %q",
++ msect.Name, msect.Seg, load.Name)
++ }
++ if uint64(msect.Offset) != uint64(load.Offset)+msect.Addr-load.Addr {
++ errorf("section %q file offset is %#x, want %#x",
++ msect.Name, msect.Offset, load.Offset+msect.Addr-load.Addr)
++ }
++ if msect.Reloff != 0 || msect.Nreloc != 0 {
++ errorf("section %q has reloff %d,%d, want %d,%d",
++ msect.Name, msect.Reloff, msect.Nreloc, 0, 0)
++ }
++ flags := uint32(0)
++ if msect.Name == "__text" {
++ flags = 0x400
++ }
++ if msect.Offset == 0 {
++ flags = 1
++ }
++ if msect.Flags != flags {
++ errorf("section %q flags = %#x, want %#x", msect.Name, msect.Flags, flags)
++ }
++ sect := &Section{
++ Name: strings.ToLower(strings.TrimPrefix(msect.Name, "__")),
++ VirtAddr: Addr(msect.Addr),
++ Size: Addr(msect.Size),
++ Align: 1 << msect.Align,
++ }
++ seg.Sections = append(seg.Sections, sect)
++ }
++ }
++ }
++
++ for _, msect := range msects {
++ errorf("section %q has no segment", msect.Name)
++ }
++
++ limit = 0
++ for _, msect := range f.Sections {
++ if msect.Addr < limit {
++ errorf("sections out of order: %q at %#x after %#x", msect.Name, msect.Addr, limit)
++ }
++ limit = msect.Addr + msect.Size
++ }
++
++ err = nil
++ if errors != nil {
++ err = fmt.Errorf("%s", strings.Join(errors, "\n\t"))
++ }
++ return prog, err
++}
+diff --git a/src/cmd/newlink/main.go b/src/cmd/newlink/main.go
+new file mode 100644
+index 0000000..b23f3f8
+--- /dev/null
++++ b/src/cmd/newlink/main.go
+@@ -0,0 +1,9 @@
++// Copyright 2014 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++// Placeholder to keep build building.
++
++package main
++
++func main() {}
+diff --git a/src/cmd/newlink/pclntab.go b/src/cmd/newlink/pclntab.go
+new file mode 100644
+index 0000000..0a4cfc9
+--- /dev/null
++++ b/src/cmd/newlink/pclntab.go
+@@ -0,0 +1,480 @@
++// Copyright 2014 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++// Generation of runtime function information (pclntab).
++
++package main
++
++import (
++ "cmd/internal/goobj"
++ "cmd/internal/obj"
++ "encoding/binary"
++ "os"
++ "sort"
++)
++
++var zerofunc goobj.Func
++
++// pclntab collects the runtime function data for each function that will
++// be listed in the binary and builds a single table describing all functions.
++// This table is used at run time for stack traces and to look up PC-specific
++// information during garbage collection. The symbol created is named
++// "pclntab" for historical reasons; the scope of the table has grown to
++// include more than just PC/line number correspondences.
++// The table format is documented at https://golang.org/s/go12symtab.
++func (p *Prog) pclntab() {
++ // Count number of functions going into the binary,
++ // so that we can size the initial index correctly.
++ nfunc := 0
++ for _, sym := range p.SymOrder {
++ if sym.Kind != goobj.STEXT {
++ continue
++ }
++ nfunc++
++ }
++
++ // Table header.
++ buf := new(SymBuffer)
++ buf.Init(p)
++ buf.SetSize(8 + p.ptrsize)
++ off := 0
++ off = buf.Uint32(off, 0xfffffffb)
++ off = buf.Uint8(off, 0)
++ off = buf.Uint8(off, 0)
++ off = buf.Uint8(off, uint8(p.pcquantum))
++ off = buf.Uint8(off, uint8(p.ptrsize))
++ off = buf.Uint(off, uint64(nfunc), p.ptrsize)
++ indexOff := off
++ off += (nfunc*2 + 1) * p.ptrsize // function index, to be filled in
++ off += 4 // file table start offset, to be filled in
++ buf.SetSize(off)
++
++ // One-file cache for reading PCData tables from package files.
++ // TODO(rsc): Better I/O strategy.
++ var (
++ file *os.File
++ fname string
++ )
++
++ // Files gives the file numbering for source file names recorded
++ // in the binary.
++ files := make(map[string]int)
++
++ // Build the table, build the index, and build the file name numbering.
++ // The loop here must visit functions in the same order that they will
++ // be stored in the binary, or else binary search over the index will fail.
++ // The runtime checks that the index is sorted properly at program start time.
++ var lastSym *Sym
++ for _, sym := range p.SymOrder {
++ if sym.Kind != goobj.STEXT {
++ continue
++ }
++ lastSym = sym
++
++ // Treat no recorded function information same as all zeros.
++ f := sym.Func
++ if f == nil {
++ f = &zerofunc
++ }
++
++ // Open package file if needed, for reading PC data.
++ if fname != sym.Package.File {
++ if file != nil {
++ file.Close()
++ }
++ var err error
++ file, err = os.Open(sym.Package.File)
++ if err != nil {
++ p.errorf("%v: %v", sym, err)
++ return
++ }
++ fname = sym.Package.File
++ }
++
++ // off is the offset of the table entry where we're going to write
++ // the encoded form of Func.
++ // indexOff is the current position in the table index;
++ // we add an entry in the index pointing at off.
++ off = (buf.Size() + p.ptrsize - 1) &^ (p.ptrsize - 1)
++ indexOff = buf.Addr(indexOff, sym.SymID, 0)
++ indexOff = buf.Uint(indexOff, uint64(off), p.ptrsize)
++
++ // The Func encoding starts with a header giving offsets
++ // to data blobs, and then the data blobs themselves.
++ // end gives the current write position for the data blobs.
++ end := off + p.ptrsize + 3*4 + 5*4 + len(f.PCData)*4 + len(f.FuncData)*p.ptrsize
++ if len(f.FuncData) > 0 {
++ end += -end & (p.ptrsize - 1)
++ }
++ buf.SetSize(end)
++
++ // entry uintptr
++ // name int32
++ // args int32
++ // frame int32
++ //
++ // The frame recorded in the object file is
++ // the frame size used in an assembly listing, which does
++ // not include the caller PC on the stack.
++ // The frame size we want to list here is the delta from
++ // this function's SP to its caller's SP, which does include
++ // the caller PC. Add p.ptrsize to f.Frame to adjust.
++ // TODO(rsc): Record the same frame size in the object file.
++ off = buf.Addr(off, sym.SymID, 0)
++ off = buf.Uint32(off, uint32(addString(buf, sym.Name)))
++ off = buf.Uint32(off, uint32(f.Args))
++ off = buf.Uint32(off, uint32(f.Frame+p.ptrsize))
++
++ // pcdata
++ off = buf.Uint32(off, uint32(addPCTable(p, buf, file, f.PCSP)))
++ off = buf.Uint32(off, uint32(addPCFileTable(p, buf, file, f.PCFile, sym, files)))
++ off = buf.Uint32(off, uint32(addPCTable(p, buf, file, f.PCLine)))
++ off = buf.Uint32(off, uint32(len(f.PCData)))
++ off = buf.Uint32(off, uint32(len(f.FuncData)))
++ for _, pcdata := range f.PCData {
++ off = buf.Uint32(off, uint32(addPCTable(p, buf, file, pcdata)))
++ }
++
++ // funcdata
++ if len(f.FuncData) > 0 {
++ off += -off & (p.ptrsize - 1) // must be pointer-aligned
++ for _, funcdata := range f.FuncData {
++ if funcdata.Sym.Name == "" {
++ off = buf.Uint(off, uint64(funcdata.Offset), p.ptrsize)
++ } else {
++ off = buf.Addr(off, funcdata.Sym, funcdata.Offset)
++ }
++ }
++ }
++
++ if off != end {
++ p.errorf("internal error: invalid math in pclntab: off=%#x end=%#x", off, end)
++ break
++ }
++ }
++ if file != nil {
++ file.Close()
++ }
++
++ // Final entry of index is end PC of last function.
++ indexOff = buf.Addr(indexOff, lastSym.SymID, int64(lastSym.Size))
++
++ // Start file table.
++ // Function index is immediately followed by offset to file table.
++ off = (buf.Size() + p.ptrsize - 1) &^ (p.ptrsize - 1)
++ buf.Uint32(indexOff, uint32(off))
++
++ // File table is an array of uint32s.
++ // The first entry gives 1+n, the size of the array.
++ // The following n entries hold offsets to string data.
++ // File number n uses the string pointed at by entry n.
++ // File number 0 is invalid.
++ buf.SetSize(off + (1+len(files))*4)
++ buf.Uint32(off, uint32(1+len(files)))
++ var filestr []string
++ for file := range files {
++ filestr = append(filestr, file)
++ }
++ sort.Strings(filestr)
++ for _, file := range filestr {
++ id := files[file]
++ buf.Uint32(off+4*id, uint32(addString(buf, file)))
++ }
++
++ pclntab := &Sym{
++ Sym: &goobj.Sym{
++ SymID: goobj.SymID{Name: "runtime.pclntab"},
++ Kind: goobj.SPCLNTAB,
++ Size: buf.Size(),
++ Reloc: buf.Reloc(),
++ },
++ Bytes: buf.Bytes(),
++ }
++ p.addSym(pclntab)
++}
++
++// addString appends the string s to the buffer b.
++// It returns the offset of the beginning of the string in the buffer.
++func addString(b *SymBuffer, s string) int {
++ off := b.Size()
++ b.SetSize(off + len(s) + 1)
++ copy(b.data[off:], s)
++ return off
++}
++
++// addPCTable appends the PC-data table stored in the file f at the location loc
++// to the symbol buffer b. It returns the offset of the beginning of the table
++// in the buffer.
++func addPCTable(p *Prog, b *SymBuffer, f *os.File, loc goobj.Data) int {
++ if loc.Size == 0 {
++ return 0
++ }
++ off := b.Size()
++ b.SetSize(off + int(loc.Size))
++ _, err := f.ReadAt(b.data[off:off+int(loc.Size)], loc.Offset)
++ if err != nil {
++ p.errorf("%v", err)
++ }
++ return off
++}
++
++// addPCFileTable is like addPCTable, but it renumbers the file names referred to by the table
++// to use the global numbering maintained in the files map. It adds new files to the
++// map as necessary.
++func addPCFileTable(p *Prog, b *SymBuffer, f *os.File, loc goobj.Data, sym *Sym, files map[string]int) int {
++ if loc.Size == 0 {
++ return 0
++ }
++ off := b.Size()
++
++ src := make([]byte, loc.Size)
++ _, err := f.ReadAt(src, loc.Offset)
++ if err != nil {
++ p.errorf("%v", err)
++ return 0
++ }
++
++ filenum := make([]int, len(sym.Func.File))
++ for i, name := range sym.Func.File {
++ num := files[name]
++ if num == 0 {
++ num = len(files) + 1
++ files[name] = num
++ }
++ filenum[i] = num
++ }
++
++ var dst []byte
++ newval := int32(-1)
++ var it PCIter
++ for it.Init(p, src); !it.Done; it.Next() {
++ // value delta
++ oldval := it.Value
++ val := oldval
++ if oldval != -1 {
++ if oldval < 0 || int(oldval) >= len(filenum) {
++ p.errorf("%s: corrupt pc-file table", sym)
++ break
++ }
++ val = int32(filenum[oldval])
++ }
++ dv := val - newval
++ newval = val
++ uv := uint32(dv<<1) ^ uint32(dv>>31)
++ dst = appendVarint(dst, uv)
++
++ // pc delta
++ dst = appendVarint(dst, it.NextPC-it.PC)
++ }
++ if it.Corrupt {
++ p.errorf("%s: corrupt pc-file table", sym)
++ }
++
++ // terminating value delta
++ dst = appendVarint(dst, 0)
++
++ b.SetSize(off + len(dst))
++ copy(b.data[off:], dst)
++ return off
++}
++
++// A SymBuffer is a buffer for preparing the data image of a
++// linker-generated symbol.
++type SymBuffer struct {
++ data []byte
++ reloc []goobj.Reloc
++ order binary.ByteOrder
++ ptrsize int
++}
++
++// Init initializes the buffer for writing.
++func (b *SymBuffer) Init(p *Prog) {
++ b.data = nil
++ b.reloc = nil
++ b.order = p.byteorder
++ b.ptrsize = p.ptrsize
++}
++
++// Bytes returns the buffer data.
++func (b *SymBuffer) Bytes() []byte {
++ return b.data
++}
++
++// SetSize sets the buffer's data size to n bytes.
++func (b *SymBuffer) SetSize(n int) {
++ for cap(b.data) < n {
++ b.data = append(b.data[:cap(b.data)], 0)
++ }
++ b.data = b.data[:n]
++}
++
++// Size returns the buffer's data size.
++func (b *SymBuffer) Size() int {
++ return len(b.data)
++}
++
++// Reloc returns the buffered relocations.
++func (b *SymBuffer) Reloc() []goobj.Reloc {
++ return b.reloc
++}
++
++// Uint8 sets the uint8 at offset off to v.
++// It returns the offset just beyond v.
++func (b *SymBuffer) Uint8(off int, v uint8) int {
++ b.data[off] = v
++ return off + 1
++}
++
++// Uint16 sets the uint16 at offset off to v.
++// It returns the offset just beyond v.
++func (b *SymBuffer) Uint16(off int, v uint16) int {
++ b.order.PutUint16(b.data[off:], v)
++ return off + 2
++}
++
++// Uint32 sets the uint32 at offset off to v.
++// It returns the offset just beyond v.
++func (b *SymBuffer) Uint32(off int, v uint32) int {
++ b.order.PutUint32(b.data[off:], v)
++ return off + 4
++}
++
++// Uint64 sets the uint64 at offset off to v.
++// It returns the offset just beyond v.
++func (b *SymBuffer) Uint64(off int, v uint64) int {
++ b.order.PutUint64(b.data[off:], v)
++ return off + 8
++}
++
++// Uint sets the size-byte unsigned integer at offset off to v.
++// It returns the offset just beyond v.
++func (b *SymBuffer) Uint(off int, v uint64, size int) int {
++ switch size {
++ case 1:
++ return b.Uint8(off, uint8(v))
++ case 2:
++ return b.Uint16(off, uint16(v))
++ case 4:
++ return b.Uint32(off, uint32(v))
++ case 8:
++ return b.Uint64(off, v)
++ }
++ panic("invalid use of SymBuffer.SetUint")
++}
++
++// Addr sets the pointer-sized address at offset off to refer
++// to symoff bytes past the start of sym. It returns the offset
++// just beyond the address.
++func (b *SymBuffer) Addr(off int, sym goobj.SymID, symoff int64) int {
++ b.reloc = append(b.reloc, goobj.Reloc{
++ Offset: off,
++ Size: b.ptrsize,
++ Sym: sym,
++ Add: int(symoff),
++ Type: obj.R_ADDR,
++ })
++ return off + b.ptrsize
++}
++
++// A PCIter implements iteration over PC-data tables.
++//
++// var it PCIter
++// for it.Init(p, data); !it.Done; it.Next() {
++// it.Value holds from it.PC up to (but not including) it.NextPC
++// }
++// if it.Corrupt {
++// data was malformed
++// }
++//
++type PCIter struct {
++ PC uint32
++ NextPC uint32
++ Value int32
++ Done bool
++ Corrupt bool
++ p []byte
++ start bool
++ pcquantum uint32
++}
++
++// Init initializes the iteration.
++// On return, if it.Done is true, the iteration is over.
++// Otherwise it.Value applies in the pc range [it.PC, it.NextPC).
++func (it *PCIter) Init(p *Prog, buf []byte) {
++ it.p = buf
++ it.PC = 0
++ it.NextPC = 0
++ it.Value = -1
++ it.start = true
++ it.pcquantum = uint32(p.pcquantum)
++ it.Done = false
++ it.Next()
++}
++
++// Next steps forward one entry in the table.
++// On return, if it.Done is true, the iteration is over.
++// Otherwise it.Value applies in the pc range [it.PC, it.NextPC).
++func (it *PCIter) Next() {
++ it.PC = it.NextPC
++ if it.Done {
++ return
++ }
++ if len(it.p) == 0 {
++ it.Done = true
++ return
++ }
++
++ // value delta
++ uv, p, ok := decodeVarint(it.p)
++ if !ok {
++ it.Done = true
++ it.Corrupt = true
++ return
++ }
++ it.p = p
++ if uv == 0 && !it.start {
++ it.Done = true
++ return
++ }
++ it.start = false
++ sv := int32(uv>>1) ^ int32(uv<<31)>>31
++ it.Value += sv
++
++ // pc delta
++ uv, it.p, ok = decodeVarint(it.p)
++ if !ok {
++ it.Done = true
++ it.Corrupt = true
++ return
++ }
++ it.NextPC = it.PC + uv*it.pcquantum
++}
++
++// decodeVarint decodes an unsigned varint from p,
++// reporting the value, the remainder of the data, and
++// whether the decoding was successful.
++func decodeVarint(p []byte) (v uint32, rest []byte, ok bool) {
++ for shift := uint(0); ; shift += 7 {
++ if len(p) == 0 {
++ return
++ }
++ c := uint32(p[0])
++ p = p[1:]
++ v |= (c & 0x7F) << shift
++ if c&0x80 == 0 {
++ break
++ }
++ }
++ return v, p, true
++}
++
++// appendVarint appends an unsigned varint encoding of v to p
++// and returns the resulting slice.
++func appendVarint(p []byte, v uint32) []byte {
++ for ; v >= 0x80; v >>= 7 {
++ p = append(p, byte(v)|0x80)
++ }
++ p = append(p, byte(v))
++ return p
++}
+diff --git a/src/cmd/newlink/pclntab_test.go b/src/cmd/newlink/pclntab_test.go
+new file mode 100644
+index 0000000..ea80806
+--- /dev/null
++++ b/src/cmd/newlink/pclntab_test.go
+@@ -0,0 +1,340 @@
++// Copyright 2014 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++package main
++
++import (
++ "bytes"
++ "cmd/internal/goobj"
++ "fmt"
++ "math/rand"
++ "sort"
++ "strings"
++ "testing"
++)
++
++// Test of pcln table encoding.
++// testdata/genpcln.go generates an assembly file with
++// pseudorandom values for the data that pclntab stores.
++// This test recomputes the same pseudorandom stream
++// and checks that the final linked binary uses those values
++// as well.
++func TestPclntab(t *testing.T) {
++ p := &Prog{
++ GOOS: "darwin",
++ GOARCH: "amd64",
++ Error: func(s string) { t.Error(s) },
++ StartSym: "start",
++ omitRuntime: true,
++ }
++ var buf bytes.Buffer
++ p.link(&buf, "testdata/pclntab.6")
++ if p.NumError > 0 {
++ return
++ }
++
++ // The algorithm for computing values here must match
++ // the one in testdata/genpcln.go.
++ for f := 0; f < 3; f++ {
++ file := "input"
++ line := 1
++ rnd := rand.New(rand.NewSource(int64(f)))
++ args := rnd.Intn(100) * 8
++ frame := 32 + rnd.Intn(32)/8*8
++ size := 200 + rnd.Intn(100)*8
++
++ name := fmt.Sprintf("func%d", f)
++ r, off, fargs, fframe, ok := findFunc(t, p, name)
++ if !ok {
++ continue // error already printed
++ }
++ if fargs != args {
++ t.Errorf("%s: args=%d, want %d", name, fargs, args)
++ }
++ if fframe != frame+8 {
++ t.Errorf("%s: frame=%d, want %d", name, fframe, frame+8)
++ }
++
++ // Check FUNCDATA 1.
++ fdata, ok := loadFuncdata(t, r, name, off, 1)
++ if ok {
++ fsym := p.Syms[goobj.SymID{Name: fmt.Sprintf("funcdata%d", f)}]
++ if fsym == nil {
++ t.Errorf("funcdata%d is missing in binary", f)
++ } else if fdata != fsym.Addr {
++ t.Errorf("%s: funcdata 1 = %#x, want %#x", name, fdata, fsym.Addr)
++ }
++ }
++
++ // Walk code checking pcdata values.
++ spadj := 0
++ pcdata1 := -1
++ pcdata2 := -1
++
++ checkPCSP(t, r, name, off, 0, 0)
++ checkPCData(t, r, name, off, 0, 0, -1)
++ checkPCData(t, r, name, off, 0, 1, -1)
++ checkPCData(t, r, name, off, 0, 2, -1)
++
++ firstpc := 4
++ for i := 0; i < size; i++ {
++ pc := firstpc + i // skip SP adjustment to allocate frame
++ if i >= 0x100 && t.Failed() {
++ break
++ }
++ // Possible SP adjustment.
++ checkPCSP(t, r, name, off, pc, frame+spadj)
++ if rnd.Intn(100) == 0 {
++ checkPCFileLine(t, r, name, off, pc, file, line)
++ checkPCData(t, r, name, off, pc, 1, pcdata1)
++ checkPCData(t, r, name, off, pc, 2, pcdata2)
++ i += 1
++ pc = firstpc + i
++ checkPCFileLine(t, r, name, off, pc-1, file, line)
++ checkPCData(t, r, name, off, pc-1, 1, pcdata1)
++ checkPCData(t, r, name, off, pc-1, 2, pcdata2)
++ checkPCSP(t, r, name, off, pc-1, frame+spadj)
++
++ if spadj <= -32 || spadj < 32 && rnd.Intn(2) == 0 {
++ spadj += 8
++ } else {
++ spadj -= 8
++ }
++ checkPCSP(t, r, name, off, pc, frame+spadj)
++ }
++
++ // Possible PCFile change.
++ if rnd.Intn(100) == 0 {
++ file = fmt.Sprintf("file%d.s", rnd.Intn(10))
++ line = rnd.Intn(100) + 1
++ }
++
++ // Possible PCLine change.
++ if rnd.Intn(10) == 0 {
++ line = rnd.Intn(1000) + 1
++ }
++
++ // Possible PCData $1 change.
++ if rnd.Intn(100) == 0 {
++ pcdata1 = rnd.Intn(1000)
++ }
++
++ // Possible PCData $2 change.
++ if rnd.Intn(100) == 0 {
++ pcdata2 = rnd.Intn(1000)
++ }
++
++ if i == 0 {
++ checkPCFileLine(t, r, name, off, 0, file, line)
++ checkPCFileLine(t, r, name, off, pc-1, file, line)
++ }
++ checkPCFileLine(t, r, name, off, pc, file, line)
++ checkPCData(t, r, name, off, pc, 1, pcdata1)
++ checkPCData(t, r, name, off, pc, 2, pcdata2)
++ }
++ }
++}
++
++// findFunc finds the function information in the pclntab of p
++// for the function with the given name.
++// It returns a symbol reader for pclntab, the offset of the function information
++// within that symbol, and the args and frame values read out of the information.
++func findFunc(t *testing.T, p *Prog, name string) (r *SymReader, off, args, frame int, ok bool) {
++ tabsym := p.Syms[goobj.SymID{Name: "runtime.pclntab"}]
++ if tabsym == nil {
++ t.Errorf("pclntab is missing in binary")
++ return
++ }
++
++ r = new(SymReader)
++ r.Init(p, tabsym)
++
++ // pclntab must with 8-byte header
++ if r.Uint32(0) != 0xfffffffb || r.Uint8(4) != 0 || r.Uint8(5) != 0 || r.Uint8(6) != uint8(p.pcquantum) || r.Uint8(7) != uint8(p.ptrsize) {
++ t.Errorf("pclntab has incorrect header %.8x", r.data[:8])
++ return
++ }
++
++ sym := p.Syms[goobj.SymID{Name: name}]
++ if sym == nil {
++ t.Errorf("%s is missing in the binary", name)
++ return
++ }
++
++ // index is nfunc addr0 off0 addr1 off1 ... addr_nfunc (sentinel)
++ nfunc := int(r.Addr(8))
++ i := sort.Search(nfunc, func(i int) bool {
++ return r.Addr(8+p.ptrsize*(1+2*i)) >= sym.Addr
++ })
++ if entry := r.Addr(8 + p.ptrsize*(1+2*i)); entry != sym.Addr {
++ indexTab := make([]Addr, 2*nfunc+1)
++ for j := range indexTab {
++ indexTab[j] = r.Addr(8 + p.ptrsize*(1+j))
++ }
++ t.Errorf("pclntab is missing entry for %s (%#x): %#x", name, sym.Addr, indexTab)
++ return
++ }
++
++ off = int(r.Addr(8 + p.ptrsize*(1+2*i+1)))
++
++ // func description at off is
++ // entry addr
++ // nameoff uint32
++ // args uint32
++ // frame uint32
++ // pcspoff uint32
++ // pcfileoff uint32
++ // pclineoff uint32
++ // npcdata uint32
++ // nfuncdata uint32
++ // pcdata npcdata*uint32
++ // funcdata nfuncdata*addr
++ //
++ if entry := r.Addr(off); entry != sym.Addr {
++ t.Errorf("pclntab inconsistent: entry for %s addr=%#x has entry=%#x", name, sym.Addr, entry)
++ return
++ }
++ nameoff := int(r.Uint32(off + p.ptrsize))
++ args = int(r.Uint32(off + p.ptrsize + 1*4))
++ frame = int(r.Uint32(off + p.ptrsize + 2*4))
++
++ fname := r.String(nameoff)
++ if fname != name {
++ t.Errorf("pclntab inconsistent: entry for %s addr=%#x has name %q", name, sym.Addr, fname)
++ }
++
++ ok = true // off, args, frame are usable
++ return
++}
++
++// loadFuncdata returns the funcdata #fnum value
++// loaded from the function information for name.
++func loadFuncdata(t *testing.T, r *SymReader, name string, off int, fnum int) (Addr, bool) {
++ npcdata := int(r.Uint32(off + r.p.ptrsize + 6*4))
++ nfuncdata := int(r.Uint32(off + r.p.ptrsize + 7*4))
++ if fnum >= nfuncdata {
++ t.Errorf("pclntab(%s): no funcdata %d (only < %d)", name, fnum, nfuncdata)
++ return 0, false
++ }
++ fdataoff := off + r.p.ptrsize + (8+npcdata)*4 + fnum*r.p.ptrsize
++ fdataoff += fdataoff & 4
++ return r.Addr(fdataoff), true
++}
++
++// checkPCSP checks that the PCSP table in the function information at off
++// lists spadj as the sp delta for pc.
++func checkPCSP(t *testing.T, r *SymReader, name string, off, pc, spadj int) {
++ pcoff := r.Uint32(off + r.p.ptrsize + 3*4)
++ pcval, ok := readPCData(t, r, name, "PCSP", pcoff, pc)
++ if !ok {
++ return
++ }
++ if pcval != spadj {
++ t.Errorf("pclntab(%s): at pc=+%#x, pcsp=%d, want %d", name, pc, pcval, spadj)
++ }
++}
++
++// checkPCSP checks that the PCFile and PCLine tables in the function information at off
++// list file, line as the file name and line number for pc.
++func checkPCFileLine(t *testing.T, r *SymReader, name string, off, pc int, file string, line int) {
++ pcfileoff := r.Uint32(off + r.p.ptrsize + 4*4)
++ pclineoff := r.Uint32(off + r.p.ptrsize + 5*4)
++ pcfilenum, ok1 := readPCData(t, r, name, "PCFile", pcfileoff, pc)
++ pcline, ok2 := readPCData(t, r, name, "PCLine", pclineoff, pc)
++ if !ok1 || !ok2 {
++ return
++ }
++ nfunc := int(r.Addr(8))
++ filetaboff := r.Uint32(8 + r.p.ptrsize*2*(nfunc+1))
++ nfile := int(r.Uint32(int(filetaboff)))
++ if pcfilenum <= 0 || pcfilenum >= nfile {
++ t.Errorf("pclntab(%s): at pc=+%#x, filenum=%d (invalid; nfile=%d)", name, pc, pcfilenum, nfile)
++ }
++ pcfile := r.String(int(r.Uint32(int(filetaboff) + pcfilenum*4)))
++ if !strings.HasSuffix(pcfile, file) {
++ t.Errorf("pclntab(%s): at pc=+%#x, file=%q, want %q", name, pc, pcfile, file)
++ }
++ if pcline != line {
++ t.Errorf("pclntab(%s): at pc=+%#x, line=%d, want %d", name, pc, pcline, line)
++ }
++}
++
++// checkPCData checks that the PCData#pnum table in the function information at off
++// list val as the value for pc.
++func checkPCData(t *testing.T, r *SymReader, name string, off, pc, pnum, val int) {
++ pcoff := r.Uint32(off + r.p.ptrsize + (8+pnum)*4)
++ pcval, ok := readPCData(t, r, name, fmt.Sprintf("PCData#%d", pnum), pcoff, pc)
++ if !ok {
++ return
++ }
++ if pcval != val {
++ t.Errorf("pclntab(%s): at pc=+%#x, pcdata#%d=%d, want %d", name, pc, pnum, pcval, val)
++ }
++}
++
++// readPCData reads the PCData table offset off
++// to obtain and return the value associated with pc.
++func readPCData(t *testing.T, r *SymReader, name, pcdataname string, pcoff uint32, pc int) (int, bool) {
++ // "If pcsp, pcfile, pcln, or any of the pcdata offsets is zero,
++ // that table is considered missing, and all PCs take value -1."
++ if pcoff == 0 {
++ return -1, true
++ }
++
++ var it PCIter
++ for it.Init(r.p, r.data[pcoff:]); !it.Done; it.Next() {
++ if it.PC <= uint32(pc) && uint32(pc) < it.NextPC {
++ return int(it.Value), true
++ }
++ }
++ if it.Corrupt {
++ t.Errorf("pclntab(%s): %s: corrupt pcdata table", name, pcdataname)
++ }
++ return 0, false
++}
++
++// A SymReader provides typed access to the data for a symbol.
++type SymReader struct {
++ p *Prog
++ data []byte
++}
++
++func (r *SymReader) Init(p *Prog, sym *Sym) {
++ seg := sym.Section.Segment
++ off := sym.Addr - seg.VirtAddr
++ data := seg.Data[off : off+Addr(sym.Size)]
++ r.p = p
++ r.data = data
++}
++
++func (r *SymReader) Uint8(off int) uint8 {
++ return r.data[off]
++}
++
++func (r *SymReader) Uint16(off int) uint16 {
++ return r.p.byteorder.Uint16(r.data[off:])
++}
++
++func (r *SymReader) Uint32(off int) uint32 {
++ return r.p.byteorder.Uint32(r.data[off:])
++}
++
++func (r *SymReader) Uint64(off int) uint64 {
++ return r.p.byteorder.Uint64(r.data[off:])
++}
++
++func (r *SymReader) Addr(off int) Addr {
++ if r.p.ptrsize == 4 {
++ return Addr(r.Uint32(off))
++ }
++ return Addr(r.Uint64(off))
++}
++
++func (r *SymReader) String(off int) string {
++ end := off
++ for r.data[end] != '\x00' {
++ end++
++ }
++ return string(r.data[off:end])
++}
+diff --git a/src/cmd/newlink/prog.go b/src/cmd/newlink/prog.go
+new file mode 100644
+index 0000000..77fb1ec
+--- /dev/null
++++ b/src/cmd/newlink/prog.go
+@@ -0,0 +1,220 @@
++// Copyright 2014 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++package main
++
++import (
++ "cmd/internal/goobj"
++ "encoding/binary"
++ "fmt"
++ "go/build"
++ "io"
++ "os"
++ "runtime"
++)
++
++// A Prog holds state for constructing an executable (program) image.
++//
++// The usual sequence of operations on a Prog is:
++//
++// p.init()
++// p.scan(file)
++// p.dead()
++// p.runtime()
++// p.layout()
++// p.load()
++// p.debug()
++// p.write(w)
++//
++// p.init is in this file. The rest of the methods are in files
++// named for the method. The convenience method p.link runs
++// this sequence.
++//
++type Prog struct {
++ // Context
++ GOOS string // target operating system
++ GOARCH string // target architecture
++ Format string // desired file format ("elf", "macho", ...)
++ Error func(string) // called to report an error (if set)
++ NumError int // number of errors printed
++ StartSym string
++
++ // Derived context
++ arch
++ formatter formatter
++ startSym goobj.SymID
++ pkgdir string
++ omitRuntime bool // do not load runtime package
++
++ // Input
++ Packages map[string]*Package // loaded packages, by import path
++ Syms map[goobj.SymID]*Sym // defined symbols, by symbol ID
++ Missing map[goobj.SymID]bool // missing symbols
++ Dead map[goobj.SymID]bool // symbols removed as dead
++ SymOrder []*Sym // order syms were scanned
++ MaxVersion int // max SymID.Version, for generating fresh symbol IDs
++
++ // Output
++ UnmappedSize Addr // size of unmapped region at address 0
++ HeaderSize Addr // size of object file header
++ Entry Addr // virtual address where execution begins
++ Segments []*Segment // loaded memory segments
++}
++
++// An arch describes architecture-dependent settings.
++type arch struct {
++ byteorder binary.ByteOrder
++ ptrsize int
++ pcquantum int
++}
++
++// A formatter takes care of the details of generating a particular
++// kind of executable file.
++type formatter interface {
++ // headerSize returns the footprint of the header for p
++ // in both virtual address space and file bytes.
++ // The footprint does not include any bytes stored at the
++ // end of the file.
++ headerSize(p *Prog) (virt, file Addr)
++
++ // write writes the executable file for p to w.
++ write(w io.Writer, p *Prog)
++}
++
++// An Addr represents a virtual memory address, a file address, or a size.
++// It must be a uint64, not a uintptr, so that a 32-bit linker can still generate a 64-bit binary.
++// It must be unsigned in order to link programs placed at very large start addresses.
++// Math involving Addrs must be checked carefully not to require negative numbers.
++type Addr uint64
++
++// A Package is a Go package loaded from a file.
++type Package struct {
++ *goobj.Package // table of contents
++ File string // file name for reopening
++ Syms []*Sym // symbols defined by this package
++}
++
++// A Sym is a symbol defined in a loaded package.
++type Sym struct {
++ *goobj.Sym // symbol metadata from package file
++ Package *Package // package defining symbol
++ Section *Section // section where symbol is placed in output program
++ Addr Addr // virtual address of symbol in output program
++ Bytes []byte // symbol data, for internally defined symbols
++}
++
++// A Segment is a loaded memory segment.
++// A Prog is expected to have segments named "text" and optionally "data",
++// in that order, before any other segments.
++type Segment struct {
++ Name string // name of segment: "text", "data", ...
++ VirtAddr Addr // virtual memory address of segment base
++ VirtSize Addr // size of segment in memory
++ FileOffset Addr // file offset of segment base
++ FileSize Addr // size of segment in file; can be less than VirtSize
++ Sections []*Section // sections inside segment
++ Data []byte // raw data of segment image
++}
++
++// A Section is part of a loaded memory segment.
++type Section struct {
++ Name string // name of section: "text", "rodata", "noptrbss", and so on
++ VirtAddr Addr // virtual memory address of section base
++ Size Addr // size of section in memory
++ Align Addr // required alignment
++ InFile bool // section has image data in file (like data, unlike bss)
++ Syms []*Sym // symbols stored in section
++ Segment *Segment // segment containing section
++}
++
++func (p *Prog) errorf(format string, args ...interface{}) {
++ if p.Error != nil {
++ p.Error(fmt.Sprintf(format, args...))
++ } else {
++ fmt.Fprintf(os.Stderr, format+"\n", args...)
++ }
++ p.NumError++
++}
++
++// link is the one-stop convenience method for running a link.
++// It writes to w the object file generated from using mainFile as the main package.
++func (p *Prog) link(w io.Writer, mainFile string) {
++ p.init()
++ p.scan(mainFile)
++ if p.NumError > 0 {
++ return
++ }
++ p.dead()
++ p.runtime()
++ p.autoData()
++ p.layout()
++ p.autoConst()
++ if p.NumError > 0 {
++ return
++ }
++ p.load()
++ if p.NumError > 0 {
++ return
++ }
++ p.debug()
++ if p.NumError > 0 {
++ return
++ }
++ p.write(w)
++}
++
++// init initializes p for use by the other methods.
++func (p *Prog) init() {
++ // Set default context if not overridden.
++ if p.GOOS == "" {
++ p.GOOS = build.Default.GOOS
++ }
++ if p.GOARCH == "" {
++ p.GOARCH = build.Default.GOARCH
++ }
++ if p.Format == "" {
++ p.Format = goosFormat[p.GOOS]
++ if p.Format == "" {
++ p.errorf("no default file format for GOOS %q", p.GOOS)
++ return
++ }
++ }
++ if p.StartSym == "" {
++ p.StartSym = fmt.Sprintf("_rt0_%s_%s", p.GOARCH, p.GOOS)
++ }
++
++ // Derive internal context.
++ p.formatter = formatters[p.Format]
++ if p.formatter == nil {
++ p.errorf("unknown output file format %q", p.Format)
++ return
++ }
++ p.startSym = goobj.SymID{Name: p.StartSym}
++ arch, ok := arches[p.GOARCH]
++ if !ok {
++ p.errorf("unknown GOOS %q", p.GOOS)
++ return
++ }
++ p.arch = arch
++
++ p.pkgdir = fmt.Sprintf("%s/pkg/%s_%s", runtime.GOROOT(), p.GOOS, p.GOARCH)
++}
++
++// goosFormat records the default format for each known GOOS value.
++var goosFormat = map[string]string{
++ "darwin": "darwin",
++}
++
++// formatters records the format implementation for each known format value.
++var formatters = map[string]formatter{
++ "darwin": machoFormat{},
++}
++
++var arches = map[string]arch{
++ "amd64": {
++ byteorder: binary.LittleEndian,
++ ptrsize: 8,
++ pcquantum: 1,
++ },
++}
+diff --git a/src/cmd/newlink/prog_test.go b/src/cmd/newlink/prog_test.go
+new file mode 100644
+index 0000000..0853506
+--- /dev/null
++++ b/src/cmd/newlink/prog_test.go
+@@ -0,0 +1,163 @@
++// Copyright 2014 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++package main
++
++import (
++ "bytes"
++ "fmt"
++ "io/ioutil"
++ "testing"
++)
++
++// shiftProg adjusts the addresses in p.
++// It adds vdelta to all virtual addresses and fdelta to all file offsets.
++func shiftProg(p *Prog, vdelta Addr, fdelta Addr) {
++ p.Entry += vdelta
++ for _, seg := range p.Segments {
++ seg.FileOffset += fdelta
++ seg.VirtAddr += vdelta
++ for _, sect := range seg.Sections {
++ sect.VirtAddr += vdelta
++ for _, sym := range sect.Syms {
++ sym.Addr += vdelta
++ }
++ }
++ }
++}
++
++// diffProg returns a list of differences between p and q,
++// assuming p is being checked and q is the correct answer.
++func diffProg(p, q *Prog) []string {
++ var errors []string
++ if p.UnmappedSize != q.UnmappedSize {
++ errors = append(errors, fmt.Sprintf("p.UnmappedSize = %#x, want %#x", p.UnmappedSize, q.UnmappedSize))
++ }
++ if p.HeaderSize != q.HeaderSize {
++ errors = append(errors, fmt.Sprintf("p.HeaderSize = %#x, want %#x", p.HeaderSize, q.HeaderSize))
++ }
++ if p.Entry != q.Entry {
++ errors = append(errors, fmt.Sprintf("p.Entry = %#x, want %#x", p.Entry, q.Entry))
++ }
++ for i := 0; i < len(p.Segments) || i < len(q.Segments); i++ {
++ if i >= len(p.Segments) {
++ errors = append(errors, fmt.Sprintf("p missing segment %q", q.Segments[i].Name))
++ continue
++ }
++ if i >= len(q.Segments) {
++ errors = append(errors, fmt.Sprintf("p has extra segment %q", p.Segments[i].Name))
++ continue
++ }
++ pseg := p.Segments[i]
++ qseg := q.Segments[i]
++ if pseg.Name != qseg.Name {
++ errors = append(errors, fmt.Sprintf("segment %d Name = %q, want %q", i, pseg.Name, qseg.Name))
++ continue // probably out of sync
++ }
++ if pseg.VirtAddr != qseg.VirtAddr {
++ errors = append(errors, fmt.Sprintf("segment %q VirtAddr = %#x, want %#x", pseg.Name, pseg.VirtAddr, qseg.VirtAddr))
++ }
++ if pseg.VirtSize != qseg.VirtSize {
++ errors = append(errors, fmt.Sprintf("segment %q VirtSize = %#x, want %#x", pseg.Name, pseg.VirtSize, qseg.VirtSize))
++ }
++ if pseg.FileOffset != qseg.FileOffset {
++ errors = append(errors, fmt.Sprintf("segment %q FileOffset = %#x, want %#x", pseg.Name, pseg.FileOffset, qseg.FileOffset))
++ }
++ if pseg.FileSize != qseg.FileSize {
++ errors = append(errors, fmt.Sprintf("segment %q FileSize = %#x, want %#x", pseg.Name, pseg.FileSize, qseg.FileSize))
++ }
++ if len(pseg.Data) != len(qseg.Data) {
++ errors = append(errors, fmt.Sprintf("segment %q len(Data) = %d, want %d", pseg.Name, len(pseg.Data), len(qseg.Data)))
++ } else if !bytes.Equal(pseg.Data, qseg.Data) {
++ errors = append(errors, fmt.Sprintf("segment %q Data mismatch:\n\thave %x\n\twant %x", pseg.Name, pseg.Data, qseg.Data))
++ }
++
++ for j := 0; j < len(pseg.Sections) || j < len(qseg.Sections); j++ {
++ if j >= len(pseg.Sections) {
++ errors = append(errors, fmt.Sprintf("segment %q missing section %q", pseg.Name, qseg.Sections[i].Name))
++ continue
++ }
++ if j >= len(qseg.Sections) {
++ errors = append(errors, fmt.Sprintf("segment %q has extra section %q", pseg.Name, pseg.Sections[i].Name))
++ continue
++ }
++ psect := pseg.Sections[j]
++ qsect := qseg.Sections[j]
++ if psect.Name != qsect.Name {
++ errors = append(errors, fmt.Sprintf("segment %q, section %d Name = %q, want %q", pseg.Name, j, psect.Name, qsect.Name))
++ continue // probably out of sync
++ }
++
++ if psect.VirtAddr != qsect.VirtAddr {
++ errors = append(errors, fmt.Sprintf("segment %q section %q VirtAddr = %#x, want %#x", pseg.Name, psect.Name, psect.VirtAddr, qsect.VirtAddr))
++ }
++ if psect.Size != qsect.Size {
++ errors = append(errors, fmt.Sprintf("segment %q section %q Size = %#x, want %#x", pseg.Name, psect.Name, psect.Size, qsect.Size))
++ }
++ if psect.Align != qsect.Align {
++ errors = append(errors, fmt.Sprintf("segment %q section %q Align = %#x, want %#x", pseg.Name, psect.Name, psect.Align, qsect.Align))
++ }
++ }
++ }
++
++ return errors
++}
++
++// cloneProg returns a deep copy of p.
++func cloneProg(p *Prog) *Prog {
++ q := new(Prog)
++ *q = *p
++ q.Segments = make([]*Segment, len(p.Segments))
++ for i, seg := range p.Segments {
++ q.Segments[i] = cloneSegment(seg)
++ }
++ return q
++}
++
++// cloneSegment returns a deep copy of seg.
++func cloneSegment(seg *Segment) *Segment {
++ t := new(Segment)
++ *t = *seg
++ t.Sections = make([]*Section, len(seg.Sections))
++ for i, sect := range seg.Sections {
++ t.Sections[i] = cloneSection(sect)
++ }
++ t.Data = make([]byte, len(seg.Data))
++ copy(t.Data, seg.Data)
++ return t
++}
++
++// cloneSection returns a deep copy of section.
++func cloneSection(sect *Section) *Section {
++ // At the moment, there's nothing we need to make a deep copy of.
++ t := new(Section)
++ *t = *sect
++ return t
++}
++
++const saveMismatch = true
++
++// checkGolden checks that data matches the named file.
++// If not, it reports the error to the test.
++func checkGolden(t *testing.T, data []byte, name string) {
++ golden := mustParseHexdumpFile(t, name)
++ if !bytes.Equal(data, golden) {
++ if saveMismatch {
++ ioutil.WriteFile(name+".raw", data, 0666)
++ ioutil.WriteFile(name+".hex", []byte(hexdump(data)), 0666)
++ }
++ // TODO(rsc): A better diff would be nice, as needed.
++ i := 0
++ for i < len(data) && i < len(golden) && data[i] == golden[i] {
++ i++
++ }
++ if i >= len(data) {
++ t.Errorf("%s: output file shorter than expected: have %d bytes, want %d", name, len(data), len(golden))
++ } else if i >= len(golden) {
++ t.Errorf("%s: output file larger than expected: have %d bytes, want %d", name, len(data), len(golden))
++ } else {
++ t.Errorf("%s: output file differs at byte %d: have %#02x, want %#02x", name, i, data[i], golden[i])
++ }
++ }
++}
+diff --git a/src/cmd/newlink/runtime.go b/src/cmd/newlink/runtime.go
+new file mode 100644
+index 0000000..acda2d2
+--- /dev/null
++++ b/src/cmd/newlink/runtime.go
+@@ -0,0 +1,28 @@
++// Copyright 2014 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++// Generation of runtime-accessible data structures.
++// See also debug.go.
++
++package main
++
++import "cmd/internal/goobj"
++
++func (p *Prog) runtime() {
++ p.pclntab()
++
++ // TODO: Implement garbage collection data.
++ p.addSym(&Sym{
++ Sym: &goobj.Sym{
++ SymID: goobj.SymID{Name: "runtime.gcdata"},
++ Kind: goobj.SRODATA,
++ },
++ })
++ p.addSym(&Sym{
++ Sym: &goobj.Sym{
++ SymID: goobj.SymID{Name: "runtime.gcbss"},
++ Kind: goobj.SRODATA,
++ },
++ })
++}
+diff --git a/src/cmd/newlink/scan.go b/src/cmd/newlink/scan.go
+new file mode 100644
+index 0000000..7feb0d8
+--- /dev/null
++++ b/src/cmd/newlink/scan.go
+@@ -0,0 +1,187 @@
++// Copyright 2014 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++// Initial scan of packages making up a program.
++
++// TODO(rsc): Rename goobj.SymID.Version to StaticID to avoid confusion with the ELF meaning of version.
++// TODO(rsc): Fix file format so that SBSS/SNOPTRBSS with data is listed as SDATA/SNOPTRDATA.
++// TODO(rsc): Parallelize scan to overlap file i/o where possible.
++
++package main
++
++import (
++ "cmd/internal/goobj"
++ "os"
++ "sort"
++ "strings"
++)
++
++// scan scans all packages making up the program, starting with package main defined in mainfile.
++func (p *Prog) scan(mainfile string) {
++ p.initScan()
++ p.scanFile("main", mainfile)
++ if len(p.Missing) > 0 && !p.omitRuntime {
++ p.scanImport("runtime")
++ }
++
++ var missing []string
++ for sym := range p.Missing {
++ if !p.isAuto(sym) {
++ missing = append(missing, sym.String())
++ }
++ }
++
++ if missing != nil {
++ sort.Strings(missing)
++ for _, sym := range missing {
++ p.errorf("undefined: %s", sym)
++ }
++ }
++
++ // TODO(rsc): Walk import graph to diagnose cycles.
++}
++
++// initScan initializes the Prog fields needed by scan.
++func (p *Prog) initScan() {
++ p.Packages = make(map[string]*Package)
++ p.Syms = make(map[goobj.SymID]*Sym)
++ p.Missing = make(map[goobj.SymID]bool)
++ p.Missing[p.startSym] = true
++}
++
++// scanFile reads file to learn about the package with the given import path.
++func (p *Prog) scanFile(pkgpath string, file string) {
++ pkg := &Package{
++ File: file,
++ }
++ p.Packages[pkgpath] = pkg
++
++ f, err := os.Open(file)
++ if err != nil {
++ p.errorf("%v", err)
++ return
++ }
++ gp, err := goobj.Parse(f, pkgpath)
++ f.Close()
++ if err != nil {
++ p.errorf("reading %s: %v", file, err)
++ return
++ }
++
++ // TODO(rsc): Change cmd/internal/goobj to record package name as gp.Name.
++ // TODO(rsc): If pkgpath == "main", check that gp.Name == "main".
++
++ pkg.Package = gp
++
++ for _, gs := range gp.Syms {
++ // TODO(rsc): Fix file format instead of this workaround.
++ if gs.Data.Size > 0 {
++ switch gs.Kind {
++ case goobj.SBSS:
++ gs.Kind = goobj.SDATA
++ case goobj.SNOPTRBSS:
++ gs.Kind = goobj.SNOPTRDATA
++ }
++ }
++
++ if gs.Version != 0 {
++ gs.Version += p.MaxVersion
++ }
++ for i := range gs.Reloc {
++ r := &gs.Reloc[i]
++ if r.Sym.Version != 0 {
++ r.Sym.Version += p.MaxVersion
++ }
++ if p.Syms[r.Sym] == nil {
++ p.Missing[r.Sym] = true
++ }
++ }
++ if gs.Func != nil {
++ for i := range gs.Func.FuncData {
++ fdata := &gs.Func.FuncData[i]
++ if fdata.Sym.Name != "" {
++ if fdata.Sym.Version != 0 {
++ fdata.Sym.Version += p.MaxVersion
++ }
++ if p.Syms[fdata.Sym] == nil {
++ p.Missing[fdata.Sym] = true
++ }
++ }
++ }
++ }
++ if old := p.Syms[gs.SymID]; old != nil {
++ // Duplicate definition of symbol. Is it okay?
++ // TODO(rsc): Write test for this code.
++ switch {
++ // If both symbols are BSS (no data), take max of sizes
++ // but otherwise ignore second symbol.
++ case old.Data.Size == 0 && gs.Data.Size == 0:
++ if old.Size < gs.Size {
++ old.Size = gs.Size
++ }
++ continue
++
++ // If one is in BSS and one is not, use the one that is not.
++ case old.Data.Size > 0 && gs.Data.Size == 0:
++ continue
++ case gs.Data.Size > 0 && old.Data.Size == 0:
++ break // install gs as new symbol below
++
++ // If either is marked as DupOK, we can keep either one.
++ // Keep the one that we saw first.
++ case old.DupOK || gs.DupOK:
++ continue
++
++ // Otherwise, there's an actual conflict:
++ default:
++ p.errorf("symbol %s defined in both %s and %s %v %v", gs.SymID, old.Package.File, file, old.Data, gs.Data)
++ continue
++ }
++ }
++ s := &Sym{
++ Sym: gs,
++ Package: pkg,
++ }
++ p.addSym(s)
++ delete(p.Missing, gs.SymID)
++
++ if s.Data.Size > int64(s.Size) {
++ p.errorf("%s: initialized data larger than symbol (%d > %d)", s, s.Data.Size, s.Size)
++ }
++ }
++ p.MaxVersion += pkg.MaxVersion
++
++ for i, pkgpath := range pkg.Imports {
++ // TODO(rsc): Fix file format to drop .a from recorded import path.
++ pkgpath = strings.TrimSuffix(pkgpath, ".a")
++ pkg.Imports[i] = pkgpath
++
++ p.scanImport(pkgpath)
++ }
++}
++
++func (p *Prog) addSym(s *Sym) {
++ pkg := s.Package
++ if pkg == nil {
++ pkg = p.Packages[""]
++ if pkg == nil {
++ pkg = &Package{}
++ p.Packages[""] = pkg
++ }
++ s.Package = pkg
++ }
++ pkg.Syms = append(pkg.Syms, s)
++ p.Syms[s.SymID] = s
++ p.SymOrder = append(p.SymOrder, s)
++}
++
++// scanImport finds the object file for the given import path and then scans it.
++func (p *Prog) scanImport(pkgpath string) {
++ if p.Packages[pkgpath] != nil {
++ return // already loaded
++ }
++
++ // TODO(rsc): Implement correct search to find file.
++ p.scanFile(pkgpath, p.pkgdir+"/"+pkgpath+".a")
++}
+diff --git a/src/cmd/newlink/testdata/Makefile b/src/cmd/newlink/testdata/Makefile
+new file mode 100644
+index 0000000..d5df474
+--- /dev/null
++++ b/src/cmd/newlink/testdata/Makefile
+@@ -0,0 +1,15 @@
++ALL=\
++ autosection.6\
++ autoweak.6\
++ dead.6\
++ hello.6\
++ layout.6\
++ pclntab.6\
++
++all: $(ALL)
++
++%.6: %.s
++ GOARCH=amd64 GOOS=darwin go tool asm -o $*.6 -I $(shell go env GOROOT)/pkg/include -trimpath=$(shell pwd) $*.s
++
++pclntab.s: genpcln.go
++ go run genpcln.go >pclntab.s
+diff --git a/src/cmd/newlink/testdata/autosection.6 b/src/cmd/newlink/testdata/autosection.6
+new file mode 100644
+index 0000000..702cab6
+Binary files /dev/null and b/src/cmd/newlink/testdata/autosection.6 differ
+diff --git a/src/cmd/newlink/testdata/autosection.s b/src/cmd/newlink/testdata/autosection.s
+new file mode 100644
+index 0000000..e0cb217
+--- /dev/null
++++ b/src/cmd/newlink/testdata/autosection.s
+@@ -0,0 +1,60 @@
++// Copyright 2014 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++// Test of section-named symbols.
++
++#include "textflag.h"
++
++TEXT start(SB),7,$0
++ MOVQ $autotab(SB),AX
++ MOVQ $autoptr(SB),AX
++ RET
++
++GLOBL zero(SB), $8
++
++GLOBL zeronoptr(SB), NOPTR, $16
++
++// text
++DATA autotab+0x00(SB)/8, $runtime·text(SB)
++DATA autotab+0x08(SB)/8, $start(SB)
++DATA autotab+0x10(SB)/8, $runtime·etext(SB)
++DATA autotab+0x18(SB)/8, $start+16(SB)
++
++// data
++DATA autotab+0x20(SB)/8, $runtime·data(SB)
++DATA autotab+0x28(SB)/8, $autotab(SB)
++DATA autotab+0x30(SB)/8, $runtime·edata(SB)
++DATA autotab+0x38(SB)/8, $nonzero+4(SB)
++
++// bss
++DATA autotab+0x40(SB)/8, $runtime·bss(SB)
++DATA autotab+0x48(SB)/8, $zero(SB)
++DATA autotab+0x50(SB)/8, $runtime·ebss(SB)
++DATA autotab+0x58(SB)/8, $zero+8(SB)
++
++// noptrdata
++DATA autotab+0x60(SB)/8, $runtime·noptrdata(SB)
++DATA autotab+0x68(SB)/8, $nonzeronoptr(SB)
++DATA autotab+0x70(SB)/8, $runtime·enoptrdata(SB)
++DATA autotab+0x78(SB)/8, $nonzeronoptr+8(SB)
++
++// noptrbss
++DATA autotab+0x80(SB)/8, $runtime·noptrbss(SB)
++DATA autotab+0x88(SB)/8, $zeronoptr(SB)
++DATA autotab+0x90(SB)/8, $runtime·enoptrbss(SB)
++DATA autotab+0x98(SB)/8, $zeronoptr+16(SB)
++
++// end
++DATA autotab+0xa0(SB)/8, $runtime·end(SB)
++DATA autotab+0xa8(SB)/8, $zeronoptr+16(SB)
++
++GLOBL autotab(SB), $0xb0
++
++DATA nonzero(SB)/4, $1
++GLOBL nonzero(SB), $4
++
++DATA nonzeronoptr(SB)/8, $2
++GLOBL nonzeronoptr(SB), NOPTR, $8
++
++GLOBL autoptr(SB), $0
+diff --git a/src/cmd/newlink/testdata/autoweak.6 b/src/cmd/newlink/testdata/autoweak.6
+new file mode 100644
+index 0000000..5c68cdb
+Binary files /dev/null and b/src/cmd/newlink/testdata/autoweak.6 differ
+diff --git a/src/cmd/newlink/testdata/autoweak.s b/src/cmd/newlink/testdata/autoweak.s
+new file mode 100644
+index 0000000..2d11330
+--- /dev/null
++++ b/src/cmd/newlink/testdata/autoweak.s
+@@ -0,0 +1,30 @@
++// Copyright 2014 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++// Test of go.weak symbols.
++
++TEXT start(SB),7,$0
++ MOVQ $autotab(SB),AX
++ MOVQ $autoptr(SB),AX
++ RET
++
++// go.weak.sym should resolve to sym, because sym is in the binary.
++DATA autotab+0(SB)/8, $go·weak·sym(SB)
++DATA autotab+8(SB)/8, $sym(SB)
++
++// go.weak.missingsym should resolve to 0, because missingsym is not in the binary.
++DATA autotab+16(SB)/8, $go·weak·missingsym(SB)
++DATA autotab+24(SB)/8, $0
++
++// go.weak.deadsym should resolve to 0, because deadsym is discarded during dead code removal
++DATA autotab+32(SB)/8, $go·weak·deadsym(SB)
++DATA autotab+40(SB)/8, $0
++
++GLOBL autotab(SB), $48
++
++GLOBL sym(SB), $1
++
++GLOBL deadsym(SB), $1
++
++GLOBL autoptr(SB), $0
+diff --git a/src/cmd/newlink/testdata/dead.6 b/src/cmd/newlink/testdata/dead.6
+new file mode 100644
+index 0000000..6f14aa2
+Binary files /dev/null and b/src/cmd/newlink/testdata/dead.6 differ
+diff --git a/src/cmd/newlink/testdata/dead.s b/src/cmd/newlink/testdata/dead.s
+new file mode 100644
+index 0000000..86f3136
+--- /dev/null
++++ b/src/cmd/newlink/testdata/dead.s
+@@ -0,0 +1,48 @@
++// Copyright 2014 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++// Test of dead code removal.
++// Symbols with names beginning with dead_ should be discarded.
++// Others should be kept.
++
++TEXT start(SB),7,$0 // start symbol
++ MOVQ $data1<>(SB), AX
++ CALL text1(SB)
++ MOVQ $text2(SB), BX
++ RET
++
++TEXT text1(SB),7,$0
++ FUNCDATA $1, funcdata+4(SB)
++ RET
++
++TEXT text2(SB),7,$0
++ MOVQ $runtime·edata(SB),BX
++ RET
++
++DATA data1<>+0(SB)/8, $data2(SB)
++DATA data1<>+8(SB)/8, $data3(SB)
++GLOBL data1<>(SB), $16
++GLOBL data2(SB), $1
++GLOBL data3(SB), $1
++GLOBL funcdata(SB), $8
++
++TEXT dead_start(SB),7,$0
++ MOVQ $dead_data1(SB), AX
++ CALL dead_text1(SB)
++ MOVQ $dead_text2(SB), BX
++ RET
++
++TEXT dead_text1(SB),7,$0
++ FUNCDATA $1, dead_funcdata+4(SB)
++ RET
++
++TEXT dead_text2(SB),7,$0
++ RET
++
++DATA dead_data1+0(SB)/8, $dead_data2(SB)
++DATA dead_data1+8(SB)/8, $dead_data3(SB)
++GLOBL dead_data1(SB), $16
++GLOBL dead_data2(SB), $1
++GLOBL dead_data3(SB), $1
++GLOBL dead_funcdata(SB), $8
+diff --git a/src/cmd/newlink/testdata/genpcln.go b/src/cmd/newlink/testdata/genpcln.go
+new file mode 100644
+index 0000000..c10eaea
+--- /dev/null
++++ b/src/cmd/newlink/testdata/genpcln.go
+@@ -0,0 +1,112 @@
++// Copyright 2014 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++// This program generates a .s file using a pseudorandom
++// value stream for the runtime function data.
++// The pclntab test checks that the linked copy
++// still has the same pseudorandom value stream.
++
++package main
++
++import (
++ "fmt"
++ "math/rand"
++)
++
++func main() {
++ fmt.Printf("// generated by genpcln.go; do not edit\n\n")
++ for f := 0; f < 3; f++ {
++ r := rand.New(rand.NewSource(int64(f)))
++ file := "input"
++ line := 1
++ args := r.Intn(100) * 8
++ frame := 32 + r.Intn(32)/8*8
++ fmt.Printf("#line %d %q\n", line, file)
++ fmt.Printf("TEXT func%d(SB),7,$%d-%d\n", f, frame, args)
++ fmt.Printf("\tFUNCDATA $1, funcdata%d(SB)\n", f)
++ fmt.Printf("#line %d %q\n", line, file)
++ size := 200 + r.Intn(100)*8
++ spadj := 0
++ flushed := 0
++ firstpc := 4
++ flush := func(i int) {
++ for i-flushed >= 10 {
++ fmt.Printf("#line %d %q\n", line, file)
++ fmt.Printf("/*%#04x*/\tMOVQ $0x123456789, AX\n", firstpc+flushed)
++ flushed += 10
++ }
++ for i-flushed >= 5 {
++ fmt.Printf("#line %d %q\n", line, file)
++ fmt.Printf("/*%#04x*/\tMOVL $0x1234567, AX\n", firstpc+flushed)
++ flushed += 5
++ }
++ for i-flushed > 0 {
++ fmt.Printf("#line %d %q\n", line, file)
++ fmt.Printf("/*%#04x*/\tBYTE $0\n", firstpc+flushed)
++ flushed++
++ }
++ }
++ for i := 0; i < size; i++ {
++ // Possible SP adjustment.
++ if r.Intn(100) == 0 {
++ flush(i)
++ fmt.Printf("#line %d %q\n", line, file)
++ if spadj <= -32 || spadj < 32 && r.Intn(2) == 0 {
++ spadj += 8
++ fmt.Printf("/*%#04x*/\tPUSHQ AX\n", firstpc+i)
++ } else {
++ spadj -= 8
++ fmt.Printf("/*%#04x*/\tPOPQ AX\n", firstpc+i)
++ }
++ i += 1
++ flushed = i
++ }
++
++ // Possible PCFile change.
++ if r.Intn(100) == 0 {
++ flush(i)
++ file = fmt.Sprintf("file%d.s", r.Intn(10))
++ line = r.Intn(100) + 1
++ }
++
++ // Possible PCLine change.
++ if r.Intn(10) == 0 {
++ flush(i)
++ line = r.Intn(1000) + 1
++ }
++
++ // Possible PCData $1 change.
++ if r.Intn(100) == 0 {
++ flush(i)
++ fmt.Printf("/*%6s*/\tPCDATA $1, $%d\n", "", r.Intn(1000))
++ }
++
++ // Possible PCData $2 change.
++ if r.Intn(100) == 0 {
++ flush(i)
++ fmt.Printf("/*%6s*/\tPCDATA $2, $%d\n", "", r.Intn(1000))
++ }
++ }
++ flush(size)
++ for spadj < 0 {
++ fmt.Printf("\tPUSHQ AX\n")
++ spadj += 8
++ }
++ for spadj > 0 {
++ fmt.Printf("\tPOPQ AX\n")
++ spadj -= 8
++ }
++ fmt.Printf("\tRET\n")
++
++ fmt.Printf("\n")
++ fmt.Printf("GLOBL funcdata%d(SB), $16\n", f)
++ }
++
++ fmt.Printf("\nTEXT start(SB),7,$0\n")
++ for f := 0; f < 3; f++ {
++ fmt.Printf("\tCALL func%d(SB)\n", f)
++ }
++ fmt.Printf("\tMOVQ $runtime·pclntab(SB), AX\n")
++ fmt.Printf("\n\tRET\n")
++}
+diff --git a/src/cmd/newlink/testdata/hello.6 b/src/cmd/newlink/testdata/hello.6
+new file mode 100644
+index 0000000..825a2a6
+Binary files /dev/null and b/src/cmd/newlink/testdata/hello.6 differ
+diff --git a/src/cmd/newlink/testdata/hello.s b/src/cmd/newlink/testdata/hello.s
+new file mode 100644
+index 0000000..32ed675
+--- /dev/null
++++ b/src/cmd/newlink/testdata/hello.s
+@@ -0,0 +1,15 @@
++TEXT _rt0_go(SB),7,$0
++ MOVL $1, DI
++ MOVL $hello<>(SB), SI
++ MOVL $12, DX
++ MOVL $0x2000004, AX
++ SYSCALL
++ MOVL $0, DI
++ MOVL $0x2000001, AX
++ SYSCALL
++ RET
++
++DATA hello<>+0(SB)/4, $"hell"
++DATA hello<>+4(SB)/4, $"o wo"
++DATA hello<>+8(SB)/4, $"rld\n"
++GLOBL hello<>(SB), $12
+diff --git a/src/cmd/newlink/testdata/layout.6 b/src/cmd/newlink/testdata/layout.6
+new file mode 100644
+index 0000000..7e2a22b
+Binary files /dev/null and b/src/cmd/newlink/testdata/layout.6 differ
+diff --git a/src/cmd/newlink/testdata/layout.s b/src/cmd/newlink/testdata/layout.s
+new file mode 100644
+index 0000000..c3e55ef
+--- /dev/null
++++ b/src/cmd/newlink/testdata/layout.s
+@@ -0,0 +1,29 @@
++// Copyright 2014 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++// Test of section assignment in layout.go.
++// Each symbol should end up in the section named by the symbol name prefix (up to the underscore).
++
++#include "textflag.h"
++
++TEXT text_start(SB),7,$0
++ MOVQ $rodata_sym(SB), AX
++ MOVQ $noptrdata_sym(SB), AX
++ MOVQ $data_sym(SB), AX
++ MOVQ $bss_sym(SB), AX
++ MOVQ $noptrbss_sym(SB), AX
++ RET
++
++DATA rodata_sym(SB)/4, $1
++GLOBL rodata_sym(SB), RODATA, $4
++
++DATA noptrdata_sym(SB)/4, $1
++GLOBL noptrdata_sym(SB), NOPTR, $4
++
++DATA data_sym(SB)/4, $1
++GLOBL data_sym(SB), $4
++
++GLOBL bss_sym(SB), $4
++
++GLOBL noptrbss_sym(SB), NOPTR, $4
+diff --git a/src/cmd/newlink/testdata/link.hello.darwin.amd64 b/src/cmd/newlink/testdata/link.hello.darwin.amd64
+new file mode 100644
+index 0000000..4c62eb1
+--- /dev/null
++++ b/src/cmd/newlink/testdata/link.hello.darwin.amd64
+@@ -0,0 +1,55 @@
++00000000 cf fa ed fe 07 00 00 01 03 00 00 00 02 00 00 00 |................|
++00000010 04 00 00 00 d0 02 00 00 01 00 00 00 00 00 00 00 |................|
++00000020 19 00 00 00 48 00 00 00 5f 5f 50 41 47 45 5a 45 |....H...__PAGEZE|
++00000030 52 4f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |RO..............|
++00000040 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
++*
++00000060 00 00 00 00 00 00 00 00 19 00 00 00 38 01 00 00 |............8...|
++00000070 5f 5f 54 45 58 54 00 00 00 00 00 00 00 00 00 00 |__TEXT..........|
++00000080 00 10 00 00 00 00 00 00 c0 10 00 00 00 00 00 00 |................|
++00000090 00 00 00 00 00 00 00 00 c0 10 00 00 00 00 00 00 |................|
++000000a0 07 00 00 00 05 00 00 00 03 00 00 00 00 00 00 00 |................|
++000000b0 5f 5f 74 65 78 74 00 00 00 00 00 00 00 00 00 00 |__text..........|
++000000c0 5f 5f 54 45 58 54 00 00 00 00 00 00 00 00 00 00 |__TEXT..........|
++000000d0 00 20 00 00 00 00 00 00 30 00 00 00 00 00 00 00 |. ......0.......|
++000000e0 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
++000000f0 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
++00000100 5f 5f 72 6f 64 61 74 61 00 00 00 00 00 00 00 00 |__rodata........|
++00000110 5f 5f 54 45 58 54 00 00 00 00 00 00 00 00 00 00 |__TEXT..........|
++00000120 30 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |0 ..............|
++00000130 30 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |0...............|
++*
++00000150 5f 5f 66 75 6e 63 74 61 62 00 00 00 00 00 00 00 |__functab.......|
++00000160 5f 5f 54 45 58 54 00 00 00 00 00 00 00 00 00 00 |__TEXT..........|
++00000170 30 20 00 00 00 00 00 00 90 00 00 00 00 00 00 00 |0 ..............|
++00000180 30 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |0...............|
++*
++000001a0 19 00 00 00 98 00 00 00 5f 5f 44 41 54 41 00 00 |........__DATA..|
++000001b0 00 00 00 00 00 00 00 00 00 30 00 00 00 00 00 00 |.........0......|
++000001c0 0c 00 00 00 00 00 00 00 00 20 00 00 00 00 00 00 |......... ......|
++000001d0 0c 00 00 00 00 00 00 00 03 00 00 00 03 00 00 00 |................|
++000001e0 01 00 00 00 00 00 00 00 5f 5f 64 61 74 61 00 00 |........__data..|
++000001f0 00 00 00 00 00 00 00 00 5f 5f 44 41 54 41 00 00 |........__DATA..|
++00000200 00 00 00 00 00 00 00 00 00 30 00 00 00 00 00 00 |.........0......|
++00000210 0c 00 00 00 00 00 00 00 00 20 00 00 00 00 00 00 |......... ......|
++*
++00000230 00 00 00 00 00 00 00 00 05 00 00 00 b8 00 00 00 |................|
++00000240 04 00 00 00 2a 00 00 00 00 00 00 00 00 00 00 00 |....*...........|
++*
++000002c0 00 00 00 00 00 00 00 00 00 20 00 00 00 00 00 00 |......... ......|
++*
++00001000 bf 01 00 00 00 8d 35 f5 0f 00 00 ba 0c 00 00 00 |......5.........|
++00001010 b8 04 00 00 02 0f 05 31 ff b8 01 00 00 02 0f 05 |.......1........|
++00001020 c3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
++00001030 fb ff ff ff 00 00 01 08 01 00 00 00 00 00 00 00 |................|
++00001040 00 20 00 00 00 00 00 00 30 00 00 00 00 00 00 00 |. ......0.......|
++00001050 30 20 00 00 00 00 00 00 80 00 00 00 00 00 00 00 |0 ..............|
++00001060 00 20 00 00 00 00 00 00 58 00 00 00 00 00 00 80 |. ......X.......|
++00001070 08 00 00 00 60 00 00 00 63 00 00 00 66 00 00 00 |....`...c...f...|
++00001080 00 00 00 00 00 00 00 00 5f 72 74 30 5f 67 6f 00 |........_rt0_go.|
++00001090 02 30 00 04 30 00 06 05 02 06 02 05 02 05 02 02 |.0..0...........|
++000010a0 02 02 02 05 02 02 02 10 00 00 00 00 00 00 00 00 |................|
++000010b0 02 00 00 00 88 00 00 00 68 65 6c 6c 6f 2e 73 00 |........hello.s.|
++*
++00002000 68 65 6c 6c 6f 20 77 6f 72 6c 64 0a |hello world.|
++0000200c
+diff --git a/src/cmd/newlink/testdata/macho.amd64.exit9 b/src/cmd/newlink/testdata/macho.amd64.exit9
+new file mode 100644
+index 0000000..1adc814
+--- /dev/null
++++ b/src/cmd/newlink/testdata/macho.amd64.exit9
+@@ -0,0 +1,24 @@
++00000000 cf fa ed fe 07 00 00 01 03 00 00 00 02 00 00 00 |................|
++00000010 03 00 00 00 98 01 00 00 01 00 00 00 00 00 00 00 |................|
++00000020 19 00 00 00 48 00 00 00 5f 5f 50 41 47 45 5a 45 |....H...__PAGEZE|
++00000030 52 4f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |RO..............|
++00000040 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
++00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
++00000060 00 00 00 00 00 00 00 00 19 00 00 00 98 00 00 00 |................|
++00000070 5f 5f 54 45 58 54 00 00 00 00 00 00 00 00 00 00 |__TEXT..........|
++00000080 00 10 00 00 00 00 00 00 0d 10 00 00 00 00 00 00 |................|
++00000090 00 00 00 00 00 00 00 00 0d 10 00 00 00 00 00 00 |................|
++000000a0 07 00 00 00 05 00 00 00 01 00 00 00 00 00 00 00 |................|
++000000b0 5f 5f 74 65 78 74 00 00 00 00 00 00 00 00 00 00 |__text..........|
++000000c0 5f 5f 54 45 58 54 00 00 00 00 00 00 00 00 00 00 |__TEXT..........|
++000000d0 00 20 00 00 00 00 00 00 0d 00 00 00 00 00 00 00 |. ..............|
++000000e0 00 10 00 00 06 00 00 00 00 00 00 00 00 00 00 00 |................|
++000000f0 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
++00000100 05 00 00 00 b8 00 00 00 04 00 00 00 2a 00 00 00 |............*...|
++00000110 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
++*
++00000190 00 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |. ..............|
++000001a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
++*
++00001000 b8 01 00 00 02 bf 09 00 00 00 0f 05 f4 |.............|
++0000100d
+diff --git a/src/cmd/newlink/testdata/macho.amd64.hello b/src/cmd/newlink/testdata/macho.amd64.hello
+new file mode 100644
+index 0000000..45e70d0
+--- /dev/null
++++ b/src/cmd/newlink/testdata/macho.amd64.hello
+@@ -0,0 +1,39 @@
++00000000 cf fa ed fe 07 00 00 01 03 00 00 00 02 00 00 00 |................|
++00000010 04 00 00 00 30 02 00 00 01 00 00 00 00 00 00 00 |....0...........|
++00000020 19 00 00 00 48 00 00 00 5f 5f 50 41 47 45 5a 45 |....H...__PAGEZE|
++00000030 52 4f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |RO..............|
++00000040 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
++00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
++00000060 00 00 00 00 00 00 00 00 19 00 00 00 98 00 00 00 |................|
++00000070 5f 5f 54 45 58 54 00 00 00 00 00 00 00 00 00 00 |__TEXT..........|
++00000080 00 10 00 00 00 00 00 00 23 10 00 00 00 00 00 00 |........#.......|
++00000090 00 00 00 00 00 00 00 00 23 10 00 00 00 00 00 00 |........#.......|
++000000a0 07 00 00 00 05 00 00 00 01 00 00 00 00 00 00 00 |................|
++000000b0 5f 5f 74 65 78 74 00 00 00 00 00 00 00 00 00 00 |__text..........|
++000000c0 5f 5f 54 45 58 54 00 00 00 00 00 00 00 00 00 00 |__TEXT..........|
++000000d0 00 20 00 00 00 00 00 00 23 00 00 00 00 00 00 00 |. ......#.......|
++000000e0 00 10 00 00 06 00 00 00 00 00 00 00 00 00 00 00 |................|
++000000f0 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
++00000100 19 00 00 00 98 00 00 00 5f 5f 44 41 54 41 00 00 |........__DATA..|
++00000110 00 00 00 00 00 00 00 00 00 30 00 00 00 00 00 00 |.........0......|
++00000120 0c 00 00 00 00 00 00 00 00 20 00 00 00 00 00 00 |......... ......|
++00000130 0c 00 00 00 00 00 00 00 03 00 00 00 03 00 00 00 |................|
++00000140 01 00 00 00 00 00 00 00 5f 5f 64 61 74 61 00 00 |........__data..|
++00000150 00 00 00 00 00 00 00 00 5f 5f 44 41 54 41 00 00 |........__DATA..|
++00000160 00 00 00 00 00 00 00 00 00 30 00 00 00 00 00 00 |.........0......|
++00000170 0c 00 00 00 00 00 00 00 00 20 00 00 06 00 00 00 |......... ......|
++00000180 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
++00000190 00 00 00 00 00 00 00 00 05 00 00 00 b8 00 00 00 |................|
++000001a0 04 00 00 00 2a 00 00 00 00 00 00 00 00 00 00 00 |....*...........|
++000001b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
++*
++00000220 00 00 00 00 00 00 00 00 00 20 00 00 00 00 00 00 |......... ......|
++00000230 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
++*
++00001000 b8 04 00 00 02 bf 01 00 00 00 be 00 30 00 00 ba |............0...|
++00001010 0c 00 00 00 0f 05 b8 01 00 00 02 bf 09 00 00 00 |................|
++00001020 0f 05 f4 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
++00001030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
++*
++00002000 68 65 6c 6c 6f 20 77 6f 72 6c 64 0a |hello world.|
++0000200c
+diff --git a/src/cmd/newlink/testdata/macho.amd64.helloro b/src/cmd/newlink/testdata/macho.amd64.helloro
+new file mode 100644
+index 0000000..4b70fbd
+--- /dev/null
++++ b/src/cmd/newlink/testdata/macho.amd64.helloro
+@@ -0,0 +1,34 @@
++00000000 cf fa ed fe 07 00 00 01 03 00 00 00 02 00 00 00 |................|
++00000010 03 00 00 00 e8 01 00 00 01 00 00 00 00 00 00 00 |................|
++00000020 19 00 00 00 48 00 00 00 5f 5f 50 41 47 45 5a 45 |....H...__PAGEZE|
++00000030 52 4f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |RO..............|
++00000040 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
++00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
++00000060 00 00 00 00 00 00 00 00 19 00 00 00 e8 00 00 00 |................|
++00000070 5f 5f 54 45 58 54 00 00 00 00 00 00 00 00 00 00 |__TEXT..........|
++00000080 00 10 00 00 00 00 00 00 0c 20 00 00 00 00 00 00 |......... ......|
++00000090 00 00 00 00 00 00 00 00 0c 20 00 00 00 00 00 00 |......... ......|
++000000a0 07 00 00 00 05 00 00 00 02 00 00 00 00 00 00 00 |................|
++000000b0 5f 5f 74 65 78 74 00 00 00 00 00 00 00 00 00 00 |__text..........|
++000000c0 5f 5f 54 45 58 54 00 00 00 00 00 00 00 00 00 00 |__TEXT..........|
++000000d0 00 20 00 00 00 00 00 00 23 00 00 00 00 00 00 00 |. ......#.......|
++000000e0 00 10 00 00 06 00 00 00 00 00 00 00 00 00 00 00 |................|
++000000f0 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
++00000100 5f 5f 72 6f 64 61 74 61 00 00 00 00 00 00 00 00 |__rodata........|
++00000110 5f 5f 54 45 58 54 00 00 00 00 00 00 00 00 00 00 |__TEXT..........|
++00000120 00 30 00 00 00 00 00 00 0c 00 00 00 00 00 00 00 |.0..............|
++00000130 00 20 00 00 06 00 00 00 00 00 00 00 00 00 00 00 |. ..............|
++00000140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
++00000150 05 00 00 00 b8 00 00 00 04 00 00 00 2a 00 00 00 |............*...|
++00000160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
++*
++000001e0 00 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |. ..............|
++000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
++*
++00001000 b8 04 00 00 02 bf 01 00 00 00 be 00 30 00 00 ba |............0...|
++00001010 0c 00 00 00 0f 05 b8 01 00 00 02 bf 00 00 00 00 |................|
++00001020 0f 05 f4 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
++00001030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
++*
++00002000 68 65 6c 6c 6f 20 77 6f 72 6c 64 0a |hello world.|
++0000200c
+diff --git a/src/cmd/newlink/testdata/pclntab.6 b/src/cmd/newlink/testdata/pclntab.6
+new file mode 100644
+index 0000000..d029bb7
+Binary files /dev/null and b/src/cmd/newlink/testdata/pclntab.6 differ
+diff --git a/src/cmd/newlink/testdata/pclntab.s b/src/cmd/newlink/testdata/pclntab.s
+new file mode 100644
+index 0000000..12dac70
+--- /dev/null
++++ b/src/cmd/newlink/testdata/pclntab.s
+@@ -0,0 +1,1751 @@
++// generated by genpcln.go; do not edit
++
++#line 1 "input"
++TEXT func0(SB),7,$48-592
++ FUNCDATA $1, funcdata0(SB)
++#line 1 "input"
++#line 1 "input"
++/*0x0004*/ MOVL $0x1234567, AX
++#line 1 "input"
++/*0x0009*/ BYTE $0
++/* */ PCDATA $1, $110
++#line 1 "input"
++/*0x000a*/ BYTE $0
++#line 1 "input"
++/*0x000b*/ BYTE $0
++/* */ PCDATA $1, $422
++#line 1 "input"
++/*0x000c*/ BYTE $0
++#line 1 "input"
++/*0x000d*/ BYTE $0
++#line 1 "input"
++/*0x000e*/ POPQ AX
++#line 1 "input"
++/*0x000f*/ MOVL $0x1234567, AX
++#line 1 "input"
++/*0x0014*/ BYTE $0
++#line 1 "input"
++/*0x0015*/ BYTE $0
++#line 1 "input"
++/*0x0016*/ BYTE $0
++#line 542 "input"
++/*0x0017*/ BYTE $0
++#line 960 "input"
++/*0x0018*/ MOVL $0x1234567, AX
++#line 960 "input"
++/*0x001d*/ BYTE $0
++#line 960 "input"
++/*0x001e*/ PUSHQ AX
++#line 960 "input"
++/*0x001f*/ BYTE $0
++#line 960 "input"
++/*0x0020*/ BYTE $0
++#line 594 "input"
++/*0x0021*/ BYTE $0
++#line 671 "input"
++/*0x0022*/ MOVL $0x1234567, AX
++#line 671 "input"
++/*0x0027*/ BYTE $0
++#line 671 "input"
++/*0x0028*/ BYTE $0
++#line 230 "input"
++/*0x0029*/ BYTE $0
++#line 230 "input"
++/*0x002a*/ BYTE $0
++#line 413 "input"
++/*0x002b*/ BYTE $0
++#line 413 "input"
++/*0x002c*/ BYTE $0
++#line 413 "input"
++/*0x002d*/ BYTE $0
++#line 729 "input"
++/*0x002e*/ BYTE $0
++#line 729 "input"
++/*0x002f*/ BYTE $0
++#line 729 "input"
++/*0x0030*/ BYTE $0
++#line 948 "input"
++/*0x0031*/ BYTE $0
++#line 11 "input"
++/*0x0032*/ MOVQ $0x123456789, AX
++#line 11 "input"
++/*0x003c*/ MOVL $0x1234567, AX
++#line 11 "input"
++/*0x0041*/ BYTE $0
++#line 11 "input"
++/*0x0042*/ BYTE $0
++#line 11 "input"
++/*0x0043*/ POPQ AX
++/* */ PCDATA $2, $342
++#line 11 "input"
++/*0x0044*/ MOVQ $0x123456789, AX
++#line 11 "input"
++/*0x004e*/ MOVQ $0x123456789, AX
++#line 11 "input"
++/*0x0058*/ MOVL $0x1234567, AX
++#line 11 "input"
++/*0x005d*/ BYTE $0
++#line 11 "input"
++/*0x005e*/ BYTE $0
++#line 70 "input"
++/*0x005f*/ BYTE $0
++#line 70 "input"
++/*0x0060*/ BYTE $0
++#line 70 "input"
++/*0x0061*/ BYTE $0
++#line 18 "input"
++/*0x0062*/ MOVQ $0x123456789, AX
++#line 18 "input"
++/*0x006c*/ MOVL $0x1234567, AX
++#line 18 "input"
++/*0x0071*/ BYTE $0
++#line 814 "input"
++/*0x0072*/ BYTE $0
++#line 814 "input"
++/*0x0073*/ PUSHQ AX
++#line 763 "input"
++/*0x0074*/ BYTE $0
++#line 763 "input"
++/*0x0075*/ BYTE $0
++#line 763 "input"
++/*0x0076*/ BYTE $0
++#line 530 "input"
++/*0x0077*/ BYTE $0
++#line 530 "input"
++/*0x0078*/ BYTE $0
++#line 530 "input"
++/*0x0079*/ BYTE $0
++#line 530 "input"
++/*0x007a*/ BYTE $0
++#line 985 "input"
++/*0x007b*/ BYTE $0
++#line 985 "input"
++/*0x007c*/ BYTE $0
++#line 985 "input"
++/*0x007d*/ BYTE $0
++#line 985 "input"
++/*0x007e*/ PUSHQ AX
++#line 985 "input"
++/*0x007f*/ MOVL $0x1234567, AX
++#line 958 "input"
++/*0x0084*/ BYTE $0
++#line 368 "input"
++/*0x0085*/ MOVQ $0x123456789, AX
++#line 368 "input"
++/*0x008f*/ MOVL $0x1234567, AX
++#line 368 "input"
++/*0x0094*/ BYTE $0
++#line 368 "input"
++/*0x0095*/ BYTE $0
++#line 368 "input"
++/*0x0096*/ BYTE $0
++#line 368 "input"
++/*0x0097*/ BYTE $0
++#line 75 "file0.s"
++/*0x0098*/ BYTE $0
++#line 75 "file0.s"
++/*0x0099*/ BYTE $0
++#line 75 "file0.s"
++/*0x009a*/ BYTE $0
++#line 75 "file0.s"
++/*0x009b*/ BYTE $0
++#line 588 "file0.s"
++/*0x009c*/ MOVQ $0x123456789, AX
++#line 187 "file0.s"
++/*0x00a6*/ MOVQ $0x123456789, AX
++#line 187 "file0.s"
++/*0x00b0*/ BYTE $0
++#line 202 "file0.s"
++/*0x00b1*/ MOVL $0x1234567, AX
++#line 202 "file0.s"
++/*0x00b6*/ BYTE $0
++#line 887 "file0.s"
++/*0x00b7*/ MOVL $0x1234567, AX
++#line 887 "file0.s"
++/*0x00bc*/ BYTE $0
++#line 887 "file0.s"
++/*0x00bd*/ BYTE $0
++#line 480 "file0.s"
++/*0x00be*/ MOVL $0x1234567, AX
++#line 480 "file0.s"
++/*0x00c3*/ BYTE $0
++#line 40 "file8.s"
++/*0x00c4*/ BYTE $0
++#line 17 "file0.s"
++/*0x00c5*/ MOVQ $0x123456789, AX
++#line 17 "file0.s"
++/*0x00cf*/ BYTE $0
++#line 17 "file0.s"
++/*0x00d0*/ BYTE $0
++#line 17 "file0.s"
++/*0x00d1*/ BYTE $0
++#line 17 "file0.s"
++/*0x00d2*/ BYTE $0
++#line 436 "file0.s"
++/*0x00d3*/ MOVL $0x1234567, AX
++#line 436 "file0.s"
++/*0x00d8*/ BYTE $0
++#line 436 "file0.s"
++/*0x00d9*/ BYTE $0
++#line 346 "file0.s"
++/*0x00da*/ BYTE $0
++#line 346 "file0.s"
++/*0x00db*/ BYTE $0
++#line 346 "file0.s"
++/*0x00dc*/ BYTE $0
++#line 812 "file0.s"
++/*0x00dd*/ BYTE $0
++#line 812 "file0.s"
++/*0x00de*/ BYTE $0
++#line 812 "file0.s"
++/*0x00df*/ BYTE $0
++#line 812 "file0.s"
++/*0x00e0*/ BYTE $0
++#line 94 "file1.s"
++/*0x00e1*/ BYTE $0
++#line 94 "file1.s"
++/*0x00e2*/ BYTE $0
++#line 165 "file1.s"
++/*0x00e3*/ MOVL $0x1234567, AX
++#line 165 "file1.s"
++/*0x00e8*/ BYTE $0
++#line 456 "file1.s"
++/*0x00e9*/ BYTE $0
++#line 810 "file1.s"
++/*0x00ea*/ BYTE $0
++#line 722 "file1.s"
++/*0x00eb*/ BYTE $0
++#line 722 "file1.s"
++/*0x00ec*/ BYTE $0
++#line 722 "file1.s"
++/*0x00ed*/ BYTE $0
++#line 722 "file1.s"
++/*0x00ee*/ BYTE $0
++#line 722 "file1.s"
++/*0x00ef*/ PUSHQ AX
++#line 722 "file1.s"
++/*0x00f0*/ BYTE $0
++#line 722 "file1.s"
++/*0x00f1*/ BYTE $0
++#line 722 "file1.s"
++/*0x00f2*/ BYTE $0
++#line 722 "file1.s"
++/*0x00f3*/ BYTE $0
++/* */ PCDATA $2, $246
++#line 722 "file1.s"
++/*0x00f4*/ MOVQ $0x123456789, AX
++#line 722 "file1.s"
++/*0x00fe*/ MOVQ $0x123456789, AX
++#line 722 "file1.s"
++/*0x0108*/ MOVL $0x1234567, AX
++#line 722 "file1.s"
++/*0x010d*/ BYTE $0
++#line 722 "file1.s"
++/*0x010e*/ BYTE $0
++#line 497 "file1.s"
++/*0x010f*/ MOVQ $0x123456789, AX
++#line 497 "file1.s"
++/*0x0119*/ MOVQ $0x123456789, AX
++#line 497 "file1.s"
++/*0x0123*/ MOVQ $0x123456789, AX
++#line 497 "file1.s"
++/*0x012d*/ MOVL $0x1234567, AX
++#line 497 "file1.s"
++/*0x0132*/ BYTE $0
++#line 686 "file1.s"
++/*0x0133*/ BYTE $0
++#line 686 "file1.s"
++/*0x0134*/ BYTE $0
++#line 248 "file1.s"
++/*0x0135*/ BYTE $0
++#line 248 "file1.s"
++/*0x0136*/ BYTE $0
++#line 248 "file1.s"
++/*0x0137*/ BYTE $0
++#line 248 "file1.s"
++/*0x0138*/ BYTE $0
++#line 307 "file1.s"
++/*0x0139*/ BYTE $0
++#line 220 "file1.s"
++/*0x013a*/ MOVL $0x1234567, AX
++#line 220 "file1.s"
++/*0x013f*/ BYTE $0
++#line 220 "file1.s"
++/*0x0140*/ BYTE $0
++#line 467 "file1.s"
++/*0x0141*/ MOVQ $0x123456789, AX
++#line 467 "file1.s"
++/*0x014b*/ BYTE $0
++#line 467 "file1.s"
++/*0x014c*/ BYTE $0
++#line 467 "file1.s"
++/*0x014d*/ BYTE $0
++#line 467 "file1.s"
++/*0x014e*/ BYTE $0
++#line 786 "file1.s"
++/*0x014f*/ MOVL $0x1234567, AX
++#line 251 "file1.s"
++/*0x0154*/ BYTE $0
++/* */ PCDATA $2, $64
++#line 251 "file1.s"
++/*0x0155*/ BYTE $0
++#line 251 "file1.s"
++/*0x0156*/ BYTE $0
++#line 251 "file1.s"
++/*0x0157*/ BYTE $0
++#line 618 "file1.s"
++/*0x0158*/ MOVQ $0x123456789, AX
++/* */ PCDATA $1, $686
++#line 618 "file1.s"
++/*0x0162*/ BYTE $0
++#line 618 "file1.s"
++/*0x0163*/ BYTE $0
++#line 618 "file1.s"
++/*0x0164*/ BYTE $0
++#line 618 "file1.s"
++/*0x0165*/ PUSHQ AX
++/* */ PCDATA $2, $915
++#line 618 "file1.s"
++/*0x0166*/ BYTE $0
++#line 618 "file1.s"
++/*0x0167*/ BYTE $0
++#line 618 "file1.s"
++/*0x0168*/ BYTE $0
++#line 618 "file1.s"
++/*0x0169*/ BYTE $0
++#line 230 "file1.s"
++/*0x016a*/ BYTE $0
++#line 823 "file1.s"
++/*0x016b*/ BYTE $0
++#line 145 "file1.s"
++/*0x016c*/ MOVQ $0x123456789, AX
++#line 145 "file1.s"
++/*0x0176*/ BYTE $0
++#line 145 "file1.s"
++/*0x0177*/ BYTE $0
++#line 675 "file1.s"
++/*0x0178*/ BYTE $0
++#line 62 "file9.s"
++/*0x0179*/ BYTE $0
++/* */ PCDATA $2, $768
++#line 62 "file9.s"
++/*0x017a*/ BYTE $0
++#line 62 "file9.s"
++/*0x017b*/ BYTE $0
++#line 29 "file9.s"
++/*0x017c*/ BYTE $0
++#line 29 "file9.s"
++/*0x017d*/ BYTE $0
++#line 29 "file9.s"
++/*0x017e*/ BYTE $0
++#line 29 "file9.s"
++/*0x017f*/ BYTE $0
++#line 65 "file4.s"
++/*0x0180*/ BYTE $0
++#line 77 "file3.s"
++/*0x0181*/ MOVL $0x1234567, AX
++#line 77 "file3.s"
++/*0x0186*/ BYTE $0
++#line 77 "file3.s"
++/*0x0187*/ BYTE $0
++#line 77 "file3.s"
++/*0x0188*/ BYTE $0
++#line 307 "file3.s"
++/*0x0189*/ MOVQ $0x123456789, AX
++#line 307 "file3.s"
++/*0x0193*/ BYTE $0
++#line 654 "file3.s"
++/*0x0194*/ BYTE $0
++#line 654 "file3.s"
++/*0x0195*/ BYTE $0
++#line 115 "file3.s"
++/*0x0196*/ MOVL $0x1234567, AX
++#line 115 "file3.s"
++/*0x019b*/ BYTE $0
++#line 115 "file3.s"
++/*0x019c*/ BYTE $0
++#line 115 "file3.s"
++/*0x019d*/ BYTE $0
++#line 115 "file3.s"
++/*0x019e*/ BYTE $0
++#line 154 "file3.s"
++/*0x019f*/ MOVQ $0x123456789, AX
++#line 166 "file3.s"
++/*0x01a9*/ BYTE $0
++#line 166 "file3.s"
++/*0x01aa*/ BYTE $0
++#line 166 "file3.s"
++/*0x01ab*/ BYTE $0
++/* */ PCDATA $1, $523
++#line 166 "file3.s"
++/*0x01ac*/ MOVL $0x1234567, AX
++#line 166 "file3.s"
++/*0x01b1*/ BYTE $0
++#line 779 "file3.s"
++/*0x01b2*/ BYTE $0
++#line 779 "file3.s"
++/*0x01b3*/ BYTE $0
++#line 515 "file3.s"
++/*0x01b4*/ BYTE $0
++#line 515 "file3.s"
++/*0x01b5*/ BYTE $0
++#line 369 "file3.s"
++/*0x01b6*/ MOVL $0x1234567, AX
++#line 369 "file3.s"
++/*0x01bb*/ BYTE $0
++#line 369 "file3.s"
++/*0x01bc*/ BYTE $0
++#line 369 "file3.s"
++/*0x01bd*/ BYTE $0
++#line 680 "file3.s"
++/*0x01be*/ BYTE $0
++#line 680 "file3.s"
++/*0x01bf*/ BYTE $0
++#line 680 "file3.s"
++/*0x01c0*/ BYTE $0
++#line 680 "file3.s"
++/*0x01c1*/ BYTE $0
++#line 131 "file3.s"
++/*0x01c2*/ MOVQ $0x123456789, AX
++#line 131 "file3.s"
++/*0x01cc*/ BYTE $0
++#line 131 "file3.s"
++/*0x01cd*/ BYTE $0
++#line 131 "file3.s"
++/*0x01ce*/ BYTE $0
++#line 131 "file3.s"
++/*0x01cf*/ BYTE $0
++#line 848 "file3.s"
++/*0x01d0*/ BYTE $0
++#line 848 "file3.s"
++/*0x01d1*/ BYTE $0
++#line 848 "file3.s"
++/*0x01d2*/ POPQ AX
++#line 848 "file3.s"
++/*0x01d3*/ BYTE $0
++#line 848 "file3.s"
++/*0x01d4*/ BYTE $0
++#line 848 "file3.s"
++/*0x01d5*/ BYTE $0
++/* */ PCDATA $1, $86
++#line 848 "file3.s"
++/*0x01d6*/ MOVL $0x1234567, AX
++#line 438 "file3.s"
++/*0x01db*/ MOVQ $0x123456789, AX
++#line 438 "file3.s"
++/*0x01e5*/ MOVL $0x1234567, AX
++#line 5 "file3.s"
++/*0x01ea*/ BYTE $0
++#line 5 "file3.s"
++/*0x01eb*/ BYTE $0
++#line 531 "file3.s"
++/*0x01ec*/ MOVQ $0x123456789, AX
++#line 531 "file3.s"
++/*0x01f6*/ MOVQ $0x123456789, AX
++#line 531 "file3.s"
++/*0x0200*/ MOVQ $0x123456789, AX
++#line 531 "file3.s"
++/*0x020a*/ MOVL $0x1234567, AX
++#line 863 "file3.s"
++/*0x020f*/ BYTE $0
++#line 733 "file3.s"
++/*0x0210*/ MOVQ $0x123456789, AX
++#line 166 "file3.s"
++/*0x021a*/ MOVQ $0x123456789, AX
++#line 166 "file3.s"
++/*0x0224*/ BYTE $0
++#line 166 "file3.s"
++/*0x0225*/ BYTE $0
++#line 166 "file3.s"
++/*0x0226*/ BYTE $0
++#line 166 "file3.s"
++/*0x0227*/ BYTE $0
++#line 54 "file3.s"
++/*0x0228*/ MOVQ $0x123456789, AX
++#line 54 "file3.s"
++/*0x0232*/ BYTE $0
++#line 54 "file3.s"
++/*0x0233*/ BYTE $0
++#line 54 "file3.s"
++/*0x0234*/ BYTE $0
++#line 20 "file4.s"
++/*0x0235*/ BYTE $0
++#line 20 "file4.s"
++/*0x0236*/ BYTE $0
++#line 546 "file4.s"
++/*0x0237*/ BYTE $0
++#line 546 "file4.s"
++/*0x0238*/ BYTE $0
++#line 74 "file4.s"
++/*0x0239*/ BYTE $0
++#line 31 "file4.s"
++/*0x023a*/ BYTE $0
++#line 31 "file4.s"
++/*0x023b*/ BYTE $0
++#line 31 "file4.s"
++/*0x023c*/ BYTE $0
++#line 31 "file4.s"
++/*0x023d*/ BYTE $0
++#line 834 "file4.s"
++/*0x023e*/ BYTE $0
++#line 834 "file4.s"
++/*0x023f*/ BYTE $0
++#line 519 "file4.s"
++/*0x0240*/ MOVL $0x1234567, AX
++#line 342 "file4.s"
++/*0x0245*/ BYTE $0
++#line 342 "file4.s"
++/*0x0246*/ BYTE $0
++#line 342 "file4.s"
++/*0x0247*/ BYTE $0
++#line 458 "file4.s"
++/*0x0248*/ BYTE $0
++#line 458 "file4.s"
++/*0x0249*/ BYTE $0
++#line 458 "file4.s"
++/*0x024a*/ BYTE $0
++#line 458 "file4.s"
++/*0x024b*/ BYTE $0
++#line 13 "file9.s"
++/*0x024c*/ BYTE $0
++#line 13 "file9.s"
++/*0x024d*/ BYTE $0
++#line 13 "file9.s"
++/*0x024e*/ BYTE $0
++#line 365 "file9.s"
++/*0x024f*/ BYTE $0
++#line 749 "file9.s"
++/*0x0250*/ MOVL $0x1234567, AX
++#line 749 "file9.s"
++/*0x0255*/ BYTE $0
++#line 749 "file9.s"
++/*0x0256*/ BYTE $0
++#line 41 "file0.s"
++/*0x0257*/ MOVL $0x1234567, AX
++#line 41 "file0.s"
++/*0x025c*/ BYTE $0
++#line 41 "file0.s"
++/*0x025d*/ BYTE $0
++#line 41 "file0.s"
++/*0x025e*/ BYTE $0
++#line 869 "file0.s"
++/*0x025f*/ BYTE $0
++#line 881 "file0.s"
++/*0x0260*/ MOVQ $0x123456789, AX
++#line 881 "file0.s"
++/*0x026a*/ MOVQ $0x123456789, AX
++ POPQ AX
++ POPQ AX
++ RET
++
++GLOBL funcdata0(SB), $16
++#line 1 "input"
++TEXT func1(SB),7,$40-648
++ FUNCDATA $1, funcdata1(SB)
++#line 1 "input"
++#line 1 "input"
++/*0x0004*/ BYTE $0
++#line 12 "file4.s"
++/*0x0005*/ MOVL $0x1234567, AX
++#line 12 "file4.s"
++/*0x000a*/ BYTE $0
++#line 12 "file4.s"
++/*0x000b*/ BYTE $0
++#line 12 "file4.s"
++/*0x000c*/ BYTE $0
++/* */ PCDATA $2, $705
++#line 12 "file4.s"
++/*0x000d*/ MOVQ $0x123456789, AX
++#line 12 "file4.s"
++/*0x0017*/ BYTE $0
++#line 633 "file4.s"
++/*0x0018*/ MOVQ $0x123456789, AX
++#line 633 "file4.s"
++/*0x0022*/ MOVL $0x1234567, AX
++#line 633 "file4.s"
++/*0x0027*/ POPQ AX
++#line 633 "file4.s"
++/*0x0028*/ BYTE $0
++#line 633 "file4.s"
++/*0x0029*/ BYTE $0
++#line 633 "file4.s"
++/*0x002a*/ BYTE $0
++#line 633 "file4.s"
++/*0x002b*/ PUSHQ AX
++#line 633 "file4.s"
++/*0x002c*/ MOVL $0x1234567, AX
++#line 997 "file4.s"
++/*0x0031*/ BYTE $0
++#line 997 "file4.s"
++/*0x0032*/ BYTE $0
++#line 997 "file4.s"
++/*0x0033*/ BYTE $0
++#line 997 "file4.s"
++/*0x0034*/ BYTE $0
++#line 997 "file4.s"
++/*0x0035*/ POPQ AX
++#line 997 "file4.s"
++/*0x0036*/ BYTE $0
++#line 997 "file4.s"
++/*0x0037*/ BYTE $0
++#line 1 "file4.s"
++/*0x0038*/ MOVQ $0x123456789, AX
++#line 1 "file4.s"
++/*0x0042*/ MOVQ $0x123456789, AX
++#line 1 "file4.s"
++/*0x004c*/ MOVQ $0x123456789, AX
++#line 1 "file4.s"
++/*0x0056*/ MOVQ $0x123456789, AX
++#line 1 "file4.s"
++/*0x0060*/ BYTE $0
++#line 922 "file4.s"
++/*0x0061*/ BYTE $0
++#line 375 "file4.s"
++/*0x0062*/ MOVL $0x1234567, AX
++/* */ PCDATA $1, $51
++#line 31 "file4.s"
++/*0x0067*/ MOVQ $0x123456789, AX
++#line 31 "file4.s"
++/*0x0071*/ BYTE $0
++#line 620 "file4.s"
++/*0x0072*/ MOVL $0x1234567, AX
++#line 620 "file4.s"
++/*0x0077*/ BYTE $0
++#line 695 "file4.s"
++/*0x0078*/ MOVL $0x1234567, AX
++#line 799 "file4.s"
++/*0x007d*/ MOVL $0x1234567, AX
++#line 41 "file4.s"
++/*0x0082*/ BYTE $0
++#line 795 "file4.s"
++/*0x0083*/ MOVL $0x1234567, AX
++#line 908 "file4.s"
++/*0x0088*/ BYTE $0
++#line 905 "file4.s"
++/*0x0089*/ BYTE $0
++#line 905 "file4.s"
++/*0x008a*/ BYTE $0
++#line 905 "file4.s"
++/*0x008b*/ BYTE $0
++#line 905 "file4.s"
++/*0x008c*/ BYTE $0
++#line 861 "file4.s"
++/*0x008d*/ MOVL $0x1234567, AX
++#line 861 "file4.s"
++/*0x0092*/ BYTE $0
++#line 861 "file4.s"
++/*0x0093*/ BYTE $0
++#line 861 "file4.s"
++/*0x0094*/ BYTE $0
++#line 861 "file4.s"
++/*0x0095*/ BYTE $0
++/* */ PCDATA $1, $192
++#line 861 "file4.s"
++/*0x0096*/ MOVQ $0x123456789, AX
++/* */ PCDATA $1, $60
++#line 861 "file4.s"
++/*0x00a0*/ MOVL $0x1234567, AX
++#line 861 "file4.s"
++/*0x00a5*/ BYTE $0
++#line 861 "file4.s"
++/*0x00a6*/ BYTE $0
++#line 56 "file6.s"
++/*0x00a7*/ MOVQ $0x123456789, AX
++#line 56 "file6.s"
++/*0x00b1*/ BYTE $0
++#line 56 "file6.s"
++/*0x00b2*/ BYTE $0
++#line 56 "file6.s"
++/*0x00b3*/ BYTE $0
++#line 204 "file6.s"
++/*0x00b4*/ BYTE $0
++#line 204 "file6.s"
++/*0x00b5*/ BYTE $0
++#line 204 "file6.s"
++/*0x00b6*/ BYTE $0
++#line 204 "file6.s"
++/*0x00b7*/ BYTE $0
++#line 979 "file6.s"
++/*0x00b8*/ MOVL $0x1234567, AX
++#line 979 "file6.s"
++/*0x00bd*/ BYTE $0
++#line 979 "file6.s"
++/*0x00be*/ BYTE $0
++#line 979 "file6.s"
++/*0x00bf*/ BYTE $0
++#line 58 "file6.s"
++/*0x00c0*/ MOVL $0x1234567, AX
++#line 238 "file6.s"
++/*0x00c5*/ MOVL $0x1234567, AX
++#line 238 "file6.s"
++/*0x00ca*/ BYTE $0
++#line 238 "file6.s"
++/*0x00cb*/ BYTE $0
++#line 699 "file2.s"
++/*0x00cc*/ MOVQ $0x123456789, AX
++#line 699 "file2.s"
++/*0x00d6*/ BYTE $0
++#line 699 "file2.s"
++/*0x00d7*/ BYTE $0
++#line 514 "file2.s"
++/*0x00d8*/ MOVL $0x1234567, AX
++#line 514 "file2.s"
++/*0x00dd*/ BYTE $0
++#line 514 "file2.s"
++/*0x00de*/ BYTE $0
++#line 108 "file2.s"
++/*0x00df*/ MOVQ $0x123456789, AX
++#line 108 "file2.s"
++/*0x00e9*/ MOVQ $0x123456789, AX
++#line 108 "file2.s"
++/*0x00f3*/ MOVL $0x1234567, AX
++#line 108 "file2.s"
++/*0x00f8*/ BYTE $0
++#line 108 "file2.s"
++/*0x00f9*/ BYTE $0
++#line 918 "file2.s"
++/*0x00fa*/ BYTE $0
++#line 918 "file2.s"
++/*0x00fb*/ BYTE $0
++#line 785 "file2.s"
++/*0x00fc*/ BYTE $0
++#line 3 "file5.s"
++/*0x00fd*/ BYTE $0
++#line 918 "file5.s"
++/*0x00fe*/ BYTE $0
++#line 918 "file5.s"
++/*0x00ff*/ BYTE $0
++#line 670 "file5.s"
++/*0x0100*/ MOVL $0x1234567, AX
++#line 670 "file5.s"
++/*0x0105*/ BYTE $0
++#line 720 "file5.s"
++/*0x0106*/ BYTE $0
++#line 384 "file5.s"
++/*0x0107*/ MOVQ $0x123456789, AX
++#line 384 "file5.s"
++/*0x0111*/ MOVQ $0x123456789, AX
++#line 384 "file5.s"
++/*0x011b*/ MOVQ $0x123456789, AX
++#line 384 "file5.s"
++/*0x0125*/ BYTE $0
++#line 384 "file5.s"
++/*0x0126*/ BYTE $0
++#line 263 "file5.s"
++/*0x0127*/ BYTE $0
++#line 750 "file5.s"
++/*0x0128*/ MOVL $0x1234567, AX
++#line 750 "file5.s"
++/*0x012d*/ BYTE $0
++#line 679 "file5.s"
++/*0x012e*/ MOVL $0x1234567, AX
++#line 679 "file5.s"
++/*0x0133*/ BYTE $0
++#line 679 "file5.s"
++/*0x0134*/ BYTE $0
++#line 679 "file5.s"
++/*0x0135*/ BYTE $0
++#line 679 "file5.s"
++/*0x0136*/ POPQ AX
++#line 171 "file5.s"
++/*0x0137*/ MOVL $0x1234567, AX
++#line 171 "file5.s"
++/*0x013c*/ BYTE $0
++#line 34 "file2.s"
++/*0x013d*/ BYTE $0
++#line 34 "file2.s"
++/*0x013e*/ BYTE $0
++#line 34 "file2.s"
++/*0x013f*/ BYTE $0
++#line 732 "file2.s"
++/*0x0140*/ BYTE $0
++#line 732 "file2.s"
++/*0x0141*/ PUSHQ AX
++#line 485 "file2.s"
++/*0x0142*/ BYTE $0
++#line 485 "file2.s"
++/*0x0143*/ BYTE $0
++#line 485 "file2.s"
++/*0x0144*/ BYTE $0
++#line 222 "file2.s"
++/*0x0145*/ BYTE $0
++#line 222 "file2.s"
++/*0x0146*/ BYTE $0
++/* */ PCDATA $1, $462
++#line 222 "file2.s"
++/*0x0147*/ MOVQ $0x123456789, AX
++#line 222 "file2.s"
++/*0x0151*/ MOVL $0x1234567, AX
++#line 222 "file2.s"
++/*0x0156*/ BYTE $0
++#line 677 "file2.s"
++/*0x0157*/ BYTE $0
++#line 117 "file2.s"
++/*0x0158*/ MOVL $0x1234567, AX
++#line 117 "file2.s"
++/*0x015d*/ BYTE $0
++#line 117 "file2.s"
++/*0x015e*/ BYTE $0
++#line 361 "file2.s"
++/*0x015f*/ MOVL $0x1234567, AX
++#line 590 "file2.s"
++/*0x0164*/ BYTE $0
++#line 590 "file2.s"
++/*0x0165*/ BYTE $0
++#line 58 "file2.s"
++/*0x0166*/ MOVL $0x1234567, AX
++#line 58 "file2.s"
++/*0x016b*/ BYTE $0
++#line 58 "file2.s"
++/*0x016c*/ BYTE $0
++#line 58 "file2.s"
++/*0x016d*/ BYTE $0
++#line 58 "file2.s"
++/*0x016e*/ BYTE $0
++#line 983 "file2.s"
++/*0x016f*/ BYTE $0
++#line 983 "file2.s"
++/*0x0170*/ BYTE $0
++#line 983 "file2.s"
++/*0x0171*/ BYTE $0
++#line 983 "file2.s"
++/*0x0172*/ BYTE $0
++#line 727 "file2.s"
++/*0x0173*/ MOVL $0x1234567, AX
++#line 450 "file2.s"
++/*0x0178*/ BYTE $0
++#line 450 "file2.s"
++/*0x0179*/ BYTE $0
++#line 450 "file2.s"
++/*0x017a*/ BYTE $0
++#line 450 "file2.s"
++/*0x017b*/ BYTE $0
++#line 334 "file2.s"
++/*0x017c*/ BYTE $0
++#line 334 "file2.s"
++/*0x017d*/ BYTE $0
++#line 334 "file2.s"
++/*0x017e*/ BYTE $0
++#line 334 "file2.s"
++/*0x017f*/ BYTE $0
++#line 465 "file2.s"
++/*0x0180*/ MOVL $0x1234567, AX
++/* */ PCDATA $1, $518
++#line 465 "file2.s"
++/*0x0185*/ MOVL $0x1234567, AX
++#line 465 "file2.s"
++/*0x018a*/ BYTE $0
++#line 465 "file2.s"
++/*0x018b*/ BYTE $0
++#line 465 "file2.s"
++/*0x018c*/ BYTE $0
++#line 465 "file2.s"
++/*0x018d*/ BYTE $0
++#line 682 "file2.s"
++/*0x018e*/ MOVL $0x1234567, AX
++#line 682 "file2.s"
++/*0x0193*/ BYTE $0
++#line 682 "file2.s"
++/*0x0194*/ BYTE $0
++#line 846 "file2.s"
++/*0x0195*/ MOVQ $0x123456789, AX
++#line 846 "file2.s"
++/*0x019f*/ BYTE $0
++#line 846 "file2.s"
++/*0x01a0*/ BYTE $0
++#line 846 "file2.s"
++/*0x01a1*/ POPQ AX
++#line 846 "file2.s"
++/*0x01a2*/ BYTE $0
++#line 846 "file2.s"
++/*0x01a3*/ BYTE $0
++#line 49 "file2.s"
++/*0x01a4*/ BYTE $0
++#line 49 "file2.s"
++/*0x01a5*/ BYTE $0
++#line 49 "file2.s"
++/*0x01a6*/ BYTE $0
++#line 726 "file2.s"
++/*0x01a7*/ MOVQ $0x123456789, AX
++#line 726 "file2.s"
++/*0x01b1*/ MOVL $0x1234567, AX
++#line 726 "file2.s"
++/*0x01b6*/ BYTE $0
++#line 726 "file2.s"
++/*0x01b7*/ BYTE $0
++#line 726 "file2.s"
++/*0x01b8*/ BYTE $0
++#line 726 "file2.s"
++/*0x01b9*/ PUSHQ AX
++#line 726 "file2.s"
++/*0x01ba*/ BYTE $0
++#line 726 "file2.s"
++/*0x01bb*/ BYTE $0
++#line 726 "file2.s"
++/*0x01bc*/ BYTE $0
++#line 726 "file2.s"
++/*0x01bd*/ BYTE $0
++#line 13 "file1.s"
++/*0x01be*/ BYTE $0
++#line 13 "file1.s"
++/*0x01bf*/ BYTE $0
++#line 13 "file1.s"
++/*0x01c0*/ BYTE $0
++#line 827 "file1.s"
++/*0x01c1*/ MOVL $0x1234567, AX
++#line 827 "file1.s"
++/*0x01c6*/ BYTE $0
++#line 827 "file1.s"
++/*0x01c7*/ BYTE $0
++#line 827 "file1.s"
++/*0x01c8*/ BYTE $0
++#line 827 "file1.s"
++/*0x01c9*/ BYTE $0
++#line 783 "file1.s"
++/*0x01ca*/ BYTE $0
++#line 783 "file1.s"
++/*0x01cb*/ BYTE $0
++#line 783 "file1.s"
++/*0x01cc*/ BYTE $0
++#line 783 "file1.s"
++/*0x01cd*/ BYTE $0
++#line 367 "file1.s"
++/*0x01ce*/ MOVQ $0x123456789, AX
++#line 367 "file1.s"
++/*0x01d8*/ MOVL $0x1234567, AX
++#line 367 "file1.s"
++/*0x01dd*/ BYTE $0
++#line 367 "file1.s"
++/*0x01de*/ BYTE $0
++#line 367 "file1.s"
++/*0x01df*/ BYTE $0
++#line 367 "file1.s"
++/*0x01e0*/ BYTE $0
++#line 581 "file1.s"
++/*0x01e1*/ BYTE $0
++#line 581 "file1.s"
++/*0x01e2*/ BYTE $0
++#line 581 "file1.s"
++/*0x01e3*/ BYTE $0
++#line 638 "file1.s"
++/*0x01e4*/ MOVQ $0x123456789, AX
++#line 638 "file1.s"
++/*0x01ee*/ MOVL $0x1234567, AX
++#line 638 "file1.s"
++/*0x01f3*/ BYTE $0
++#line 638 "file1.s"
++/*0x01f4*/ BYTE $0
++#line 638 "file1.s"
++/*0x01f5*/ BYTE $0
++#line 359 "file1.s"
++/*0x01f6*/ BYTE $0
++#line 449 "file1.s"
++/*0x01f7*/ BYTE $0
++#line 449 "file1.s"
++/*0x01f8*/ BYTE $0
++#line 449 "file1.s"
++/*0x01f9*/ BYTE $0
++#line 298 "file1.s"
++/*0x01fa*/ BYTE $0
++#line 298 "file1.s"
++/*0x01fb*/ BYTE $0
++#line 257 "file1.s"
++/*0x01fc*/ BYTE $0
++#line 257 "file1.s"
++/*0x01fd*/ BYTE $0
++#line 257 "file1.s"
++/*0x01fe*/ BYTE $0
++#line 512 "file1.s"
++/*0x01ff*/ MOVL $0x1234567, AX
++#line 512 "file1.s"
++/*0x0204*/ BYTE $0
++#line 512 "file1.s"
++/*0x0205*/ BYTE $0
++#line 617 "file1.s"
++/*0x0206*/ MOVL $0x1234567, AX
++#line 478 "file1.s"
++/*0x020b*/ BYTE $0
++/* */ PCDATA $2, $351
++#line 478 "file1.s"
++/*0x020c*/ BYTE $0
++#line 958 "file1.s"
++/*0x020d*/ BYTE $0
++#line 958 "file1.s"
++/*0x020e*/ BYTE $0
++#line 958 "file1.s"
++/*0x020f*/ BYTE $0
++#line 958 "file1.s"
++/*0x0210*/ BYTE $0
++#line 371 "file1.s"
++/*0x0211*/ MOVQ $0x123456789, AX
++#line 371 "file1.s"
++/*0x021b*/ BYTE $0
++#line 371 "file1.s"
++/*0x021c*/ BYTE $0
++#line 56 "file3.s"
++/*0x021d*/ MOVL $0x1234567, AX
++#line 56 "file3.s"
++/*0x0222*/ BYTE $0
++#line 56 "file3.s"
++/*0x0223*/ BYTE $0
++#line 56 "file9.s"
++/*0x0224*/ MOVQ $0x123456789, AX
++#line 56 "file9.s"
++/*0x022e*/ BYTE $0
++#line 56 "file9.s"
++/*0x022f*/ BYTE $0
++#line 56 "file9.s"
++/*0x0230*/ BYTE $0
++#line 56 "file9.s"
++/*0x0231*/ BYTE $0
++#line 684 "file9.s"
++/*0x0232*/ MOVQ $0x123456789, AX
++#line 684 "file9.s"
++/*0x023c*/ BYTE $0
++#line 684 "file9.s"
++/*0x023d*/ POPQ AX
++#line 407 "file9.s"
++/*0x023e*/ MOVL $0x1234567, AX
++#line 407 "file9.s"
++/*0x0243*/ BYTE $0
++ PUSHQ AX
++ PUSHQ AX
++ RET
++
++GLOBL funcdata1(SB), $16
++#line 1 "input"
++TEXT func2(SB),7,$40-688
++ FUNCDATA $1, funcdata2(SB)
++#line 1 "input"
++#line 1 "input"
++/*0x0004*/ BYTE $0
++#line 860 "input"
++/*0x0005*/ BYTE $0
++#line 860 "input"
++/*0x0006*/ BYTE $0
++#line 860 "input"
++/*0x0007*/ BYTE $0
++#line 860 "input"
++/*0x0008*/ BYTE $0
++#line 85 "input"
++/*0x0009*/ BYTE $0
++#line 85 "input"
++/*0x000a*/ BYTE $0
++#line 355 "input"
++/*0x000b*/ MOVQ $0x123456789, AX
++#line 355 "input"
++/*0x0015*/ MOVL $0x1234567, AX
++#line 355 "input"
++/*0x001a*/ BYTE $0
++#line 355 "input"
++/*0x001b*/ BYTE $0
++#line 355 "input"
++/*0x001c*/ BYTE $0
++#line 840 "input"
++/*0x001d*/ MOVL $0x1234567, AX
++#line 840 "input"
++/*0x0022*/ BYTE $0
++#line 294 "input"
++/*0x0023*/ MOVQ $0x123456789, AX
++#line 294 "input"
++/*0x002d*/ MOVQ $0x123456789, AX
++#line 294 "input"
++/*0x0037*/ MOVQ $0x123456789, AX
++#line 294 "input"
++/*0x0041*/ BYTE $0
++#line 294 "input"
++/*0x0042*/ BYTE $0
++#line 294 "input"
++/*0x0043*/ BYTE $0
++#line 294 "input"
++/*0x0044*/ BYTE $0
++/* */ PCDATA $1, $385
++#line 294 "input"
++/*0x0045*/ BYTE $0
++#line 294 "input"
++/*0x0046*/ BYTE $0
++#line 294 "input"
++/*0x0047*/ BYTE $0
++#line 81 "file9.s"
++/*0x0048*/ MOVL $0x1234567, AX
++#line 81 "file9.s"
++/*0x004d*/ BYTE $0
++#line 81 "file9.s"
++/*0x004e*/ BYTE $0
++#line 81 "file9.s"
++/*0x004f*/ POPQ AX
++#line 81 "file9.s"
++/*0x0050*/ MOVL $0x1234567, AX
++#line 81 "file9.s"
++/*0x0055*/ BYTE $0
++/* */ PCDATA $1, $701
++#line 81 "file9.s"
++/*0x0056*/ MOVL $0x1234567, AX
++#line 81 "file9.s"
++/*0x005b*/ BYTE $0
++#line 81 "file9.s"
++/*0x005c*/ BYTE $0
++#line 81 "file9.s"
++/*0x005d*/ BYTE $0
++#line 81 "file9.s"
++/*0x005e*/ BYTE $0
++#line 290 "file9.s"
++/*0x005f*/ BYTE $0
++#line 290 "file9.s"
++/*0x0060*/ BYTE $0
++#line 290 "file9.s"
++/*0x0061*/ BYTE $0
++#line 197 "file9.s"
++/*0x0062*/ MOVL $0x1234567, AX
++#line 197 "file9.s"
++/*0x0067*/ BYTE $0
++#line 608 "file9.s"
++/*0x0068*/ MOVQ $0x123456789, AX
++#line 608 "file9.s"
++/*0x0072*/ MOVQ $0x123456789, AX
++#line 608 "file9.s"
++/*0x007c*/ BYTE $0
++/* */ PCDATA $1, $562
++#line 608 "file9.s"
++/*0x007d*/ BYTE $0
++#line 608 "file9.s"
++/*0x007e*/ BYTE $0
++#line 189 "file9.s"
++/*0x007f*/ MOVL $0x1234567, AX
++#line 189 "file9.s"
++/*0x0084*/ BYTE $0
++#line 189 "file9.s"
++/*0x0085*/ BYTE $0
++#line 189 "file9.s"
++/*0x0086*/ BYTE $0
++#line 189 "file9.s"
++/*0x0087*/ BYTE $0
++#line 472 "file9.s"
++/*0x0088*/ MOVL $0x1234567, AX
++#line 472 "file9.s"
++/*0x008d*/ BYTE $0
++#line 472 "file9.s"
++/*0x008e*/ BYTE $0
++#line 472 "file9.s"
++/*0x008f*/ PUSHQ AX
++#line 472 "file9.s"
++/*0x0090*/ MOVQ $0x123456789, AX
++#line 472 "file9.s"
++/*0x009a*/ MOVL $0x1234567, AX
++#line 472 "file9.s"
++/*0x009f*/ BYTE $0
++#line 472 "file9.s"
++/*0x00a0*/ BYTE $0
++#line 472 "file9.s"
++/*0x00a1*/ BYTE $0
++#line 472 "file9.s"
++/*0x00a2*/ BYTE $0
++#line 148 "file9.s"
++/*0x00a3*/ MOVQ $0x123456789, AX
++#line 148 "file9.s"
++/*0x00ad*/ BYTE $0
++#line 148 "file9.s"
++/*0x00ae*/ BYTE $0
++#line 148 "file9.s"
++/*0x00af*/ BYTE $0
++#line 148 "file9.s"
++/*0x00b0*/ BYTE $0
++#line 562 "file9.s"
++/*0x00b1*/ MOVL $0x1234567, AX
++#line 562 "file9.s"
++/*0x00b6*/ BYTE $0
++#line 562 "file9.s"
++/*0x00b7*/ PUSHQ AX
++#line 562 "file9.s"
++/*0x00b8*/ BYTE $0
++#line 532 "file9.s"
++/*0x00b9*/ MOVQ $0x123456789, AX
++#line 532 "file9.s"
++/*0x00c3*/ MOVQ $0x123456789, AX
++#line 282 "file9.s"
++/*0x00cd*/ BYTE $0
++#line 282 "file9.s"
++/*0x00ce*/ BYTE $0
++#line 282 "file9.s"
++/*0x00cf*/ BYTE $0
++/* */ PCDATA $2, $861
++#line 282 "file9.s"
++/*0x00d0*/ BYTE $0
++#line 282 "file9.s"
++/*0x00d1*/ BYTE $0
++/* */ PCDATA $2, $310
++#line 282 "file9.s"
++/*0x00d2*/ BYTE $0
++#line 416 "file9.s"
++/*0x00d3*/ MOVQ $0x123456789, AX
++#line 416 "file9.s"
++/*0x00dd*/ MOVL $0x1234567, AX
++#line 780 "file9.s"
++/*0x00e2*/ BYTE $0
++#line 780 "file9.s"
++/*0x00e3*/ BYTE $0
++#line 765 "file9.s"
++/*0x00e4*/ MOVL $0x1234567, AX
++#line 523 "file9.s"
++/*0x00e9*/ BYTE $0
++#line 523 "file9.s"
++/*0x00ea*/ BYTE $0
++#line 523 "file9.s"
++/*0x00eb*/ BYTE $0
++#line 733 "file9.s"
++/*0x00ec*/ MOVQ $0x123456789, AX
++#line 378 "file9.s"
++/*0x00f6*/ BYTE $0
++#line 378 "file9.s"
++/*0x00f7*/ BYTE $0
++#line 378 "file9.s"
++/*0x00f8*/ BYTE $0
++#line 378 "file9.s"
++/*0x00f9*/ BYTE $0
++#line 540 "file9.s"
++/*0x00fa*/ BYTE $0
++#line 540 "file9.s"
++/*0x00fb*/ BYTE $0
++#line 57 "file9.s"
++/*0x00fc*/ BYTE $0
++#line 57 "file9.s"
++/*0x00fd*/ BYTE $0
++#line 57 "file9.s"
++/*0x00fe*/ BYTE $0
++#line 417 "file9.s"
++/*0x00ff*/ BYTE $0
++/* */ PCDATA $1, $932
++#line 417 "file9.s"
++/*0x0100*/ BYTE $0
++#line 417 "file9.s"
++/*0x0101*/ BYTE $0
++#line 417 "file9.s"
++/*0x0102*/ BYTE $0
++#line 417 "file9.s"
++/*0x0103*/ BYTE $0
++#line 713 "file9.s"
++/*0x0104*/ MOVL $0x1234567, AX
++#line 610 "file0.s"
++/*0x0109*/ MOVQ $0x123456789, AX
++#line 610 "file0.s"
++/*0x0113*/ MOVL $0x1234567, AX
++#line 610 "file0.s"
++/*0x0118*/ BYTE $0
++#line 787 "file0.s"
++/*0x0119*/ MOVQ $0x123456789, AX
++#line 829 "file0.s"
++/*0x0123*/ BYTE $0
++#line 829 "file0.s"
++/*0x0124*/ BYTE $0
++#line 829 "file0.s"
++/*0x0125*/ BYTE $0
++#line 849 "file0.s"
++/*0x0126*/ BYTE $0
++#line 849 "file0.s"
++/*0x0127*/ BYTE $0
++#line 849 "file0.s"
++/*0x0128*/ BYTE $0
++/* */ PCDATA $2, $356
++#line 849 "file0.s"
++/*0x0129*/ BYTE $0
++#line 849 "file0.s"
++/*0x012a*/ BYTE $0
++#line 88 "file0.s"
++/*0x012b*/ MOVL $0x1234567, AX
++#line 88 "file0.s"
++/*0x0130*/ BYTE $0
++#line 88 "file0.s"
++/*0x0131*/ BYTE $0
++#line 88 "file0.s"
++/*0x0132*/ BYTE $0
++#line 684 "file0.s"
++/*0x0133*/ BYTE $0
++#line 684 "file0.s"
++/*0x0134*/ BYTE $0
++#line 684 "file0.s"
++/*0x0135*/ BYTE $0
++#line 684 "file0.s"
++/*0x0136*/ BYTE $0
++#line 238 "file0.s"
++/*0x0137*/ BYTE $0
++#line 238 "file0.s"
++/*0x0138*/ BYTE $0
++#line 238 "file0.s"
++/*0x0139*/ PUSHQ AX
++#line 238 "file0.s"
++/*0x013a*/ BYTE $0
++#line 238 "file0.s"
++/*0x013b*/ BYTE $0
++#line 603 "file0.s"
++/*0x013c*/ BYTE $0
++#line 981 "file0.s"
++/*0x013d*/ BYTE $0
++#line 981 "file0.s"
++/*0x013e*/ POPQ AX
++#line 616 "file0.s"
++/*0x013f*/ BYTE $0
++#line 616 "file0.s"
++/*0x0140*/ BYTE $0
++#line 616 "file0.s"
++/*0x0141*/ BYTE $0
++#line 616 "file0.s"
++/*0x0142*/ BYTE $0
++#line 716 "file0.s"
++/*0x0143*/ MOVL $0x1234567, AX
++#line 716 "file0.s"
++/*0x0148*/ BYTE $0
++#line 716 "file0.s"
++/*0x0149*/ BYTE $0
++#line 34 "file0.s"
++/*0x014a*/ BYTE $0
++#line 34 "file0.s"
++/*0x014b*/ BYTE $0
++#line 34 "file0.s"
++/*0x014c*/ BYTE $0
++#line 90 "file0.s"
++/*0x014d*/ MOVL $0x1234567, AX
++#line 316 "file0.s"
++/*0x0152*/ MOVQ $0x123456789, AX
++#line 230 "file0.s"
++/*0x015c*/ MOVQ $0x123456789, AX
++#line 799 "file0.s"
++/*0x0166*/ MOVQ $0x123456789, AX
++#line 799 "file0.s"
++/*0x0170*/ BYTE $0
++#line 799 "file0.s"
++/*0x0171*/ BYTE $0
++/* */ PCDATA $1, $247
++#line 799 "file0.s"
++/*0x0172*/ BYTE $0
++#line 799 "file0.s"
++/*0x0173*/ BYTE $0
++#line 799 "file0.s"
++/*0x0174*/ BYTE $0
++#line 655 "file0.s"
++/*0x0175*/ MOVL $0x1234567, AX
++#line 655 "file0.s"
++/*0x017a*/ BYTE $0
++#line 551 "file0.s"
++/*0x017b*/ BYTE $0
++#line 551 "file0.s"
++/*0x017c*/ BYTE $0
++#line 271 "file0.s"
++/*0x017d*/ MOVQ $0x123456789, AX
++#line 271 "file0.s"
++/*0x0187*/ MOVQ $0x123456789, AX
++#line 271 "file0.s"
++/*0x0191*/ MOVL $0x1234567, AX
++#line 271 "file0.s"
++/*0x0196*/ BYTE $0
++#line 271 "file0.s"
++/*0x0197*/ BYTE $0
++#line 271 "file0.s"
++/*0x0198*/ BYTE $0
++#line 233 "file0.s"
++/*0x0199*/ MOVL $0x1234567, AX
++#line 233 "file0.s"
++/*0x019e*/ BYTE $0
++#line 233 "file0.s"
++/*0x019f*/ BYTE $0
++#line 233 "file0.s"
++/*0x01a0*/ BYTE $0
++#line 233 "file0.s"
++/*0x01a1*/ BYTE $0
++#line 738 "file0.s"
++/*0x01a2*/ MOVL $0x1234567, AX
++#line 738 "file0.s"
++/*0x01a7*/ BYTE $0
++#line 800 "file0.s"
++/*0x01a8*/ BYTE $0
++#line 800 "file0.s"
++/*0x01a9*/ BYTE $0
++#line 646 "file0.s"
++/*0x01aa*/ MOVQ $0x123456789, AX
++#line 646 "file0.s"
++/*0x01b4*/ BYTE $0
++#line 646 "file0.s"
++/*0x01b5*/ BYTE $0
++#line 646 "file0.s"
++/*0x01b6*/ BYTE $0
++#line 709 "file0.s"
++/*0x01b7*/ BYTE $0
++#line 709 "file0.s"
++/*0x01b8*/ BYTE $0
++#line 709 "file0.s"
++/*0x01b9*/ BYTE $0
++#line 709 "file0.s"
++/*0x01ba*/ BYTE $0
++#line 296 "file0.s"
++/*0x01bb*/ BYTE $0
++#line 296 "file0.s"
++/*0x01bc*/ BYTE $0
++#line 296 "file0.s"
++/*0x01bd*/ BYTE $0
++#line 71 "file0.s"
++/*0x01be*/ BYTE $0
++#line 71 "file0.s"
++/*0x01bf*/ BYTE $0
++#line 71 "file0.s"
++/*0x01c0*/ BYTE $0
++#line 7 "file2.s"
++/*0x01c1*/ BYTE $0
++#line 747 "file2.s"
++/*0x01c2*/ BYTE $0
++#line 177 "file2.s"
++/*0x01c3*/ MOVQ $0x123456789, AX
++#line 177 "file2.s"
++/*0x01cd*/ MOVQ $0x123456789, AX
++#line 177 "file2.s"
++/*0x01d7*/ MOVL $0x1234567, AX
++#line 177 "file2.s"
++/*0x01dc*/ BYTE $0
++#line 177 "file2.s"
++/*0x01dd*/ BYTE $0
++#line 177 "file2.s"
++/*0x01de*/ BYTE $0
++#line 72 "file2.s"
++/*0x01df*/ BYTE $0
++#line 215 "file2.s"
++/*0x01e0*/ MOVL $0x1234567, AX
++#line 215 "file2.s"
++/*0x01e5*/ BYTE $0
++#line 215 "file2.s"
++/*0x01e6*/ BYTE $0
++#line 215 "file2.s"
++/*0x01e7*/ BYTE $0
++#line 946 "file2.s"
++/*0x01e8*/ BYTE $0
++#line 946 "file2.s"
++/*0x01e9*/ BYTE $0
++#line 946 "file2.s"
++/*0x01ea*/ BYTE $0
++#line 946 "file2.s"
++/*0x01eb*/ BYTE $0
++#line 263 "file2.s"
++/*0x01ec*/ MOVL $0x1234567, AX
++#line 263 "file2.s"
++/*0x01f1*/ BYTE $0
++#line 897 "file2.s"
++/*0x01f2*/ MOVQ $0x123456789, AX
++#line 897 "file2.s"
++/*0x01fc*/ MOVQ $0x123456789, AX
++#line 897 "file2.s"
++/*0x0206*/ BYTE $0
++#line 897 "file2.s"
++/*0x0207*/ BYTE $0
++#line 897 "file2.s"
++/*0x0208*/ BYTE $0
++#line 229 "file2.s"
++/*0x0209*/ BYTE $0
++#line 229 "file2.s"
++/*0x020a*/ BYTE $0
++#line 229 "file2.s"
++/*0x020b*/ BYTE $0
++#line 229 "file2.s"
++/*0x020c*/ BYTE $0
++/* */ PCDATA $1, $7
++#line 229 "file2.s"
++/*0x020d*/ MOVL $0x1234567, AX
++#line 229 "file2.s"
++/*0x0212*/ BYTE $0
++#line 353 "file2.s"
++/*0x0213*/ BYTE $0
++#line 353 "file2.s"
++/*0x0214*/ BYTE $0
++#line 353 "file2.s"
++/*0x0215*/ BYTE $0
++#line 353 "file2.s"
++/*0x0216*/ BYTE $0
++#line 852 "file2.s"
++/*0x0217*/ BYTE $0
++#line 852 "file2.s"
++/*0x0218*/ BYTE $0
++#line 852 "file2.s"
++/*0x0219*/ BYTE $0
++#line 852 "file2.s"
++/*0x021a*/ BYTE $0
++#line 852 "file2.s"
++/*0x021b*/ PUSHQ AX
++#line 852 "file2.s"
++/*0x021c*/ BYTE $0
++#line 852 "file2.s"
++/*0x021d*/ BYTE $0
++#line 852 "file2.s"
++/*0x021e*/ BYTE $0
++#line 904 "file2.s"
++/*0x021f*/ MOVQ $0x123456789, AX
++#line 904 "file2.s"
++/*0x0229*/ BYTE $0
++#line 904 "file2.s"
++/*0x022a*/ BYTE $0
++#line 882 "file2.s"
++/*0x022b*/ BYTE $0
++#line 905 "file2.s"
++/*0x022c*/ BYTE $0
++#line 410 "file2.s"
++/*0x022d*/ MOVQ $0x123456789, AX
++#line 410 "file2.s"
++/*0x0237*/ BYTE $0
++#line 410 "file2.s"
++/*0x0238*/ BYTE $0
++#line 410 "file2.s"
++/*0x0239*/ POPQ AX
++#line 410 "file2.s"
++/*0x023a*/ BYTE $0
++#line 410 "file2.s"
++/*0x023b*/ BYTE $0
++#line 410 "file2.s"
++/*0x023c*/ BYTE $0
++/* */ PCDATA $2, $173
++#line 410 "file2.s"
++/*0x023d*/ MOVL $0x1234567, AX
++#line 410 "file2.s"
++/*0x0242*/ BYTE $0
++/* */ PCDATA $1, $396
++#line 410 "file2.s"
++/*0x0243*/ BYTE $0
++#line 410 "file2.s"
++/*0x0244*/ BYTE $0
++#line 666 "file2.s"
++/*0x0245*/ BYTE $0
++#line 129 "file2.s"
++/*0x0246*/ MOVQ $0x123456789, AX
++#line 129 "file2.s"
++/*0x0250*/ BYTE $0
++#line 391 "file2.s"
++/*0x0251*/ BYTE $0
++#line 696 "file2.s"
++/*0x0252*/ MOVL $0x1234567, AX
++#line 940 "file2.s"
++/*0x0257*/ BYTE $0
++#line 940 "file2.s"
++/*0x0258*/ BYTE $0
++#line 606 "file2.s"
++/*0x0259*/ MOVL $0x1234567, AX
++#line 606 "file2.s"
++/*0x025e*/ BYTE $0
++#line 648 "file2.s"
++/*0x025f*/ MOVQ $0x123456789, AX
++#line 648 "file2.s"
++/*0x0269*/ BYTE $0
++#line 648 "file2.s"
++/*0x026a*/ BYTE $0
++/* */ PCDATA $2, $84
++#line 648 "file2.s"
++/*0x026b*/ MOVQ $0x123456789, AX
++#line 648 "file2.s"
++/*0x0275*/ MOVQ $0x123456789, AX
++#line 648 "file2.s"
++/*0x027f*/ MOVQ $0x123456789, AX
++#line 648 "file2.s"
++/*0x0289*/ MOVQ $0x123456789, AX
++#line 648 "file2.s"
++/*0x0293*/ MOVQ $0x123456789, AX
++#line 648 "file2.s"
++/*0x029d*/ MOVL $0x1234567, AX
++#line 648 "file2.s"
++/*0x02a2*/ PUSHQ AX
++#line 648 "file2.s"
++/*0x02a3*/ MOVL $0x1234567, AX
++#line 648 "file2.s"
++/*0x02a8*/ BYTE $0
++#line 648 "file2.s"
++/*0x02a9*/ BYTE $0
++#line 648 "file2.s"
++/*0x02aa*/ BYTE $0
++#line 648 "file2.s"
++/*0x02ab*/ BYTE $0
++#line 449 "file2.s"
++/*0x02ac*/ MOVQ $0x123456789, AX
++#line 449 "file2.s"
++/*0x02b6*/ MOVL $0x1234567, AX
++#line 284 "file2.s"
++/*0x02bb*/ BYTE $0
++#line 284 "file2.s"
++/*0x02bc*/ BYTE $0
++#line 284 "file2.s"
++/*0x02bd*/ BYTE $0
++#line 284 "file2.s"
++/*0x02be*/ BYTE $0
++#line 26 "file2.s"
++/*0x02bf*/ MOVQ $0x123456789, AX
++#line 26 "file2.s"
++/*0x02c9*/ MOVL $0x1234567, AX
++#line 26 "file2.s"
++/*0x02ce*/ BYTE $0
++#line 26 "file2.s"
++/*0x02cf*/ BYTE $0
++#line 26 "file2.s"
++/*0x02d0*/ BYTE $0
++#line 605 "file2.s"
++/*0x02d1*/ MOVL $0x1234567, AX
++#line 605 "file2.s"
++/*0x02d6*/ BYTE $0
++#line 605 "file2.s"
++/*0x02d7*/ BYTE $0
++#line 605 "file2.s"
++/*0x02d8*/ BYTE $0
++#line 593 "file2.s"
++/*0x02d9*/ MOVL $0x1234567, AX
++#line 541 "file2.s"
++/*0x02de*/ MOVL $0x1234567, AX
++#line 541 "file2.s"
++/*0x02e3*/ BYTE $0
++#line 541 "file2.s"
++/*0x02e4*/ BYTE $0
++#line 181 "file2.s"
++/*0x02e5*/ MOVQ $0x123456789, AX
++#line 181 "file2.s"
++/*0x02ef*/ BYTE $0
++#line 907 "file2.s"
++/*0x02f0*/ MOVQ $0x123456789, AX
++#line 704 "file2.s"
++/*0x02fa*/ MOVQ $0x123456789, AX
++#line 704 "file2.s"
++/*0x0304*/ MOVQ $0x123456789, AX
++#line 704 "file2.s"
++/*0x030e*/ MOVL $0x1234567, AX
++#line 704 "file2.s"
++/*0x0313*/ BYTE $0
++#line 704 "file2.s"
++/*0x0314*/ BYTE $0
++#line 704 "file2.s"
++/*0x0315*/ BYTE $0
++#line 704 "file2.s"
++/*0x0316*/ BYTE $0
++#line 859 "file2.s"
++/*0x0317*/ MOVL $0x1234567, AX
++#line 407 "file2.s"
++/*0x031c*/ BYTE $0
++#line 407 "file2.s"
++/*0x031d*/ BYTE $0
++/* */ PCDATA $2, $569
++#line 407 "file2.s"
++/*0x031e*/ MOVL $0x1234567, AX
++#line 407 "file2.s"
++/*0x0323*/ BYTE $0
++#line 407 "file2.s"
++/*0x0324*/ BYTE $0
++#line 407 "file2.s"
++/*0x0325*/ BYTE $0
++/* */ PCDATA $1, $937
++#line 407 "file2.s"
++/*0x0326*/ MOVL $0x1234567, AX
++#line 407 "file2.s"
++/*0x032b*/ BYTE $0
++#line 774 "file2.s"
++/*0x032c*/ MOVQ $0x123456789, AX
++#line 774 "file2.s"
++/*0x0336*/ BYTE $0
++#line 547 "file2.s"
++/*0x0337*/ BYTE $0
++#line 547 "file2.s"
++/*0x0338*/ BYTE $0
++#line 547 "file2.s"
++/*0x0339*/ BYTE $0
++#line 547 "file2.s"
++/*0x033a*/ PUSHQ AX
++#line 547 "file2.s"
++/*0x033b*/ MOVL $0x1234567, AX
++#line 427 "file2.s"
++/*0x0340*/ MOVL $0x1234567, AX
++/* */ PCDATA $1, $462
++#line 427 "file2.s"
++/*0x0345*/ MOVQ $0x123456789, AX
++#line 427 "file2.s"
++/*0x034f*/ MOVL $0x1234567, AX
++#line 427 "file2.s"
++/*0x0354*/ BYTE $0
++#line 427 "file2.s"
++/*0x0355*/ BYTE $0
++#line 427 "file2.s"
++/*0x0356*/ BYTE $0
++#line 427 "file2.s"
++/*0x0357*/ BYTE $0
++/* */ PCDATA $2, $303
++#line 427 "file2.s"
++/*0x0358*/ MOVQ $0x123456789, AX
++#line 427 "file2.s"
++/*0x0362*/ BYTE $0
++#line 427 "file2.s"
++/*0x0363*/ BYTE $0
++#line 708 "file2.s"
++/*0x0364*/ BYTE $0
++#line 708 "file2.s"
++/*0x0365*/ BYTE $0
++#line 708 "file2.s"
++/*0x0366*/ BYTE $0
++#line 708 "file2.s"
++/*0x0367*/ BYTE $0
++#line 218 "file2.s"
++/*0x0368*/ MOVL $0x1234567, AX
++#line 44 "file2.s"
++/*0x036d*/ BYTE $0
++#line 915 "file2.s"
++/*0x036e*/ BYTE $0
++#line 915 "file2.s"
++/*0x036f*/ BYTE $0
++#line 915 "file2.s"
++/*0x0370*/ BYTE $0
++#line 915 "file2.s"
++/*0x0371*/ BYTE $0
++#line 122 "file2.s"
++/*0x0372*/ MOVQ $0x123456789, AX
++#line 122 "file2.s"
++/*0x037c*/ MOVL $0x1234567, AX
++#line 122 "file2.s"
++/*0x0381*/ BYTE $0
++#line 122 "file2.s"
++/*0x0382*/ BYTE $0
++#line 266 "file2.s"
++/*0x0383*/ BYTE $0
++#line 266 "file2.s"
++/*0x0384*/ BYTE $0
++#line 368 "file2.s"
++/*0x0385*/ BYTE $0
++#line 368 "file2.s"
++/*0x0386*/ BYTE $0
++#line 368 "file2.s"
++/*0x0387*/ BYTE $0
++#line 368 "file2.s"
++/*0x0388*/ BYTE $0
++#line 775 "file2.s"
++/*0x0389*/ BYTE $0
++#line 10 "file8.s"
++/*0x038a*/ BYTE $0
++#line 10 "file8.s"
++/*0x038b*/ BYTE $0
++#line 422 "file8.s"
++/*0x038c*/ MOVL $0x1234567, AX
++#line 422 "file8.s"
++/*0x0391*/ BYTE $0
++#line 613 "file8.s"
++/*0x0392*/ BYTE $0
++#line 613 "file8.s"
++/*0x0393*/ BYTE $0
++#line 613 "file8.s"
++/*0x0394*/ BYTE $0
++#line 697 "file8.s"
++/*0x0395*/ MOVQ $0x123456789, AX
++#line 697 "file8.s"
++/*0x039f*/ MOVQ $0x123456789, AX
++#line 697 "file8.s"
++/*0x03a9*/ BYTE $0
++#line 697 "file8.s"
++/*0x03aa*/ BYTE $0
++#line 697 "file8.s"
++/*0x03ab*/ BYTE $0
++ POPQ AX
++ POPQ AX
++ POPQ AX
++ RET
++
++GLOBL funcdata2(SB), $16
++
++TEXT start(SB),7,$0
++ CALL func0(SB)
++ CALL func1(SB)
++ CALL func2(SB)
++ MOVQ $runtime·pclntab(SB), AX
++
++ RET
+diff --git a/src/cmd/newlink/util.go b/src/cmd/newlink/util.go
+new file mode 100644
+index 0000000..b8a6b2c
+--- /dev/null
++++ b/src/cmd/newlink/util.go
+@@ -0,0 +1,11 @@
++// Copyright 2014 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++package main
++
++// round returns size rounded up to the next multiple of align;
++// align must be a power of two.
++func round(size, align Addr) Addr {
++ return (size + align - 1) &^ (align - 1)
++}
+diff --git a/src/cmd/newlink/write.go b/src/cmd/newlink/write.go
+new file mode 100644
+index 0000000..7e11b2f
+--- /dev/null
++++ b/src/cmd/newlink/write.go
+@@ -0,0 +1,14 @@
++// Copyright 2014 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++// Writing of executable and (for hostlink mode) object files.
++
++package main
++
++import "io"
++
++func (p *Prog) write(w io.Writer) {
++ p.Entry = p.Syms[p.startSym].Addr
++ p.formatter.write(w, p)
++}
+diff --git a/src/cmd/objdump/objdump_test.go b/src/cmd/objdump/objdump_test.go
+index 8ceaba0..cd55e16 100644
+--- a/src/cmd/objdump/objdump_test.go
++++ b/src/cmd/objdump/objdump_test.go
+@@ -107,6 +107,8 @@ func TestDisasm(t *testing.T) {
+ t.Skipf("skipping on %s, issue 10106", runtime.GOARCH)
+ case "mips64", "mips64le":
+ t.Skipf("skipping on %s, issue 12559", runtime.GOARCH)
++ case "s390x":
++ t.Skipf("skipping on %s", runtime.GOARCH)
+ }
+ testDisasm(t)
+ }
+@@ -123,6 +125,8 @@ func TestDisasmExtld(t *testing.T) {
+ t.Skipf("skipping on %s, issue 10106", runtime.GOARCH)
+ case "mips64", "mips64le":
+ t.Skipf("skipping on %s, issue 12559 and 12560", runtime.GOARCH)
++ case "s390x":
++ t.Skipf("skipping on %s", runtime.GOARCH)
+ }
+ // TODO(jsing): Reenable once openbsd/arm has external linking support.
+ if runtime.GOOS == "openbsd" && runtime.GOARCH == "arm" {
+diff --git a/src/cmd/vet/asmdecl.go b/src/cmd/vet/asmdecl.go
+index e4a9871..025d3e0 100644
+--- a/src/cmd/vet/asmdecl.go
++++ b/src/cmd/vet/asmdecl.go
+@@ -65,6 +65,7 @@ var (
+ asmArchAmd64p32 = asmArch{"amd64p32", 4, 4, 8, false, "SP", false}
+ asmArchPpc64 = asmArch{"ppc64", 8, 8, 8, true, "R1", true}
+ asmArchPpc64LE = asmArch{"ppc64le", 8, 8, 8, false, "R1", true}
++ asmArchS390x = asmArch{"s390x", 8, 8, 8, true, "R15", true}
+
+ arches = []*asmArch{
+ &asmArch386,
+@@ -74,6 +75,7 @@ var (
+ &asmArchAmd64p32,
+ &asmArchPpc64,
+ &asmArchPpc64LE,
++ &asmArchS390x,
+ }
+ )
+
+diff --git a/src/crypto/aes/asm_s390x.s b/src/crypto/aes/asm_s390x.s
+new file mode 100644
+index 0000000..c9cf166
+--- /dev/null
++++ b/src/crypto/aes/asm_s390x.s
+@@ -0,0 +1,97 @@
++// Copyright 2016 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++#include "textflag.h"
++
++// func hasAsm() bool
++// returns whether the AES-128, AES-192 and AES-256
++// cipher message functions are supported.
++TEXT ·hasAsm(SB),NOSPLIT,$16-1
++ XOR R0, R0 // set function code to 0 (query)
++ LA 8(R15), R1
++ WORD $0xB92E0024 // KM-Query
++
++ // check if bits 18-20 are set
++ MOVD 8(R15), R2
++ SRD $40, R2
++ AND $0x38, R2 // mask bits 18-20 (00111000)
+ CMPBNE R2, $0x38, notfound
+ MOVBZ $1, R1
+ MOVB R1, ret+0(FP)
@@ -21684,6 +32404,147 @@ index 6620aef..1fcc8a8 100644
(t.Data[7] != 4 && t.Data[7] != 8) { // pointer size
return
}
+diff --git a/src/encoding/csv/writer.go b/src/encoding/csv/writer.go
+index 353d91f..a605628 100644
+--- a/src/encoding/csv/writer.go
++++ b/src/encoding/csv/writer.go
+@@ -130,7 +130,7 @@ func (w *Writer) fieldNeedsQuotes(field string) bool {
+ if field == "" {
+ return false
+ }
+- if field == `\.` || strings.IndexRune(field, w.Comma) >= 0 || strings.IndexAny(field, "\"\r\n") >= 0 {
++ if field == `\.` || strings.ContainsRune(field, w.Comma) || strings.ContainsAny(field, "\"\r\n") {
+ return true
+ }
+
+diff --git a/src/encoding/gob/codec_test.go b/src/encoding/gob/codec_test.go
+index 8efcdc7..b772171 100644
+--- a/src/encoding/gob/codec_test.go
++++ b/src/encoding/gob/codec_test.go
+@@ -970,7 +970,7 @@ func TestBadRecursiveType(t *testing.T) {
+ err := NewEncoder(b).Encode(&rec)
+ if err == nil {
+ t.Error("expected error; got none")
+- } else if strings.Index(err.Error(), "recursive") < 0 {
++ } else if !strings.Contains(err.Error(), "recursive") {
+ t.Error("expected recursive type error; got", err)
+ }
+ // Can't test decode easily because we can't encode one, so we can't pass one to a Decoder.
+diff --git a/src/encoding/gob/encoder_test.go b/src/encoding/gob/encoder_test.go
+index 570d796..811dd2b 100644
+--- a/src/encoding/gob/encoder_test.go
++++ b/src/encoding/gob/encoder_test.go
+@@ -280,7 +280,7 @@ func TestValueError(t *testing.T) {
+ }
+ t4p := &Type4{3}
+ var t4 Type4 // note: not a pointer.
+- if err := encAndDec(t4p, t4); err == nil || strings.Index(err.Error(), "pointer") < 0 {
++ if err := encAndDec(t4p, t4); err == nil || !strings.Contains(err.Error(), "pointer") {
+ t.Error("expected error about pointer; got", err)
+ }
+ }
+@@ -388,7 +388,7 @@ func TestSingletons(t *testing.T) {
+ t.Errorf("expected error decoding %v: %s", test.in, test.err)
+ continue
+ case err != nil && test.err != "":
+- if strings.Index(err.Error(), test.err) < 0 {
++ if !strings.Contains(err.Error(), test.err) {
+ t.Errorf("wrong error decoding %v: wanted %s, got %v", test.in, test.err, err)
+ }
+ continue
+@@ -414,7 +414,7 @@ func TestStructNonStruct(t *testing.T) {
+ var ns NonStruct
+ if err := encAndDec(s, &ns); err == nil {
+ t.Error("should get error for struct/non-struct")
+- } else if strings.Index(err.Error(), "type") < 0 {
++ } else if !strings.Contains(err.Error(), "type") {
+ t.Error("for struct/non-struct expected type error; got", err)
+ }
+ // Now try the other way
+@@ -424,7 +424,7 @@ func TestStructNonStruct(t *testing.T) {
+ }
+ if err := encAndDec(ns, &s); err == nil {
+ t.Error("should get error for non-struct/struct")
+- } else if strings.Index(err.Error(), "type") < 0 {
++ } else if !strings.Contains(err.Error(), "type") {
+ t.Error("for non-struct/struct expected type error; got", err)
+ }
+ }
+diff --git a/src/encoding/gob/gobencdec_test.go b/src/encoding/gob/gobencdec_test.go
+index eb76b48..d674f0c 100644
+--- a/src/encoding/gob/gobencdec_test.go
++++ b/src/encoding/gob/gobencdec_test.go
+@@ -548,7 +548,7 @@ func TestGobEncoderFieldTypeError(t *testing.T) {
+ if err == nil {
+ t.Fatal("expected decode error for mismatched fields (encoder to non-decoder)")
+ }
+- if strings.Index(err.Error(), "type") < 0 {
++ if !strings.Contains(err.Error(), "type") {
+ t.Fatal("expected type error; got", err)
+ }
+ // Non-encoder to GobDecoder: error
+@@ -562,7 +562,7 @@ func TestGobEncoderFieldTypeError(t *testing.T) {
+ if err == nil {
+ t.Fatal("expected decode error for mismatched fields (non-encoder to decoder)")
+ }
+- if strings.Index(err.Error(), "type") < 0 {
++ if !strings.Contains(err.Error(), "type") {
+ t.Fatal("expected type error; got", err)
+ }
+ }
+diff --git a/src/encoding/xml/marshal.go b/src/encoding/xml/marshal.go
+index 8ebd693..9fcd5d7 100644
+--- a/src/encoding/xml/marshal.go
++++ b/src/encoding/xml/marshal.go
+@@ -850,7 +850,7 @@ func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error {
+ switch k {
+ case reflect.String:
+ s := vf.String()
+- dashDash = strings.Index(s, "--") >= 0
++ dashDash = strings.Contains(s, "--")
+ dashLast = s[len(s)-1] == '-'
+ if !dashDash {
+ p.WriteString(s)
+diff --git a/src/fmt/scan_test.go b/src/fmt/scan_test.go
+index 7ac74dc..ce6f086 100644
+--- a/src/fmt/scan_test.go
++++ b/src/fmt/scan_test.go
+@@ -519,7 +519,7 @@ func testScanfMulti(name string, t *testing.T) {
+ if err != nil {
+ if test.err == "" {
+ t.Errorf("got error scanning (%q, %q): %q", test.format, test.text, err)
+- } else if strings.Index(err.Error(), test.err) < 0 {
++ } else if !strings.Contains(err.Error(), test.err) {
+ t.Errorf("got wrong error scanning (%q, %q): %q; expected %q", test.format, test.text, err, test.err)
+ }
+ continue
+@@ -613,7 +613,7 @@ func TestScanNotPointer(t *testing.T) {
+ _, err := Fscan(r, a)
+ if err == nil {
+ t.Error("expected error scanning non-pointer")
+- } else if strings.Index(err.Error(), "pointer") < 0 {
++ } else if !strings.Contains(err.Error(), "pointer") {
+ t.Errorf("expected pointer error scanning non-pointer, got: %s", err)
+ }
+ }
+@@ -623,7 +623,7 @@ func TestScanlnNoNewline(t *testing.T) {
+ _, err := Sscanln("1 x\n", &a)
+ if err == nil {
+ t.Error("expected error scanning string missing newline")
+- } else if strings.Index(err.Error(), "newline") < 0 {
++ } else if !strings.Contains(err.Error(), "newline") {
+ t.Errorf("expected newline error scanning string missing newline, got: %s", err)
+ }
+ }
+@@ -634,7 +634,7 @@ func TestScanlnWithMiddleNewline(t *testing.T) {
+ _, err := Fscanln(r, &a, &b)
+ if err == nil {
+ t.Error("expected error scanning string with extra newline")
+- } else if strings.Index(err.Error(), "newline") < 0 {
++ } else if !strings.Contains(err.Error(), "newline") {
+ t.Errorf("expected newline error scanning string with extra newline, got: %s", err)
+ }
+ }
diff --git a/src/go/build/build.go b/src/go/build/build.go
index c1b70bc..4cfc4be 100644
--- a/src/go/build/build.go
@@ -21696,6 +32557,62 @@ index c1b70bc..4cfc4be 100644
}
func defaultContext() Context {
+diff --git a/src/go/constant/value.go b/src/go/constant/value.go
+index 310814d..1b0938d 100644
+--- a/src/go/constant/value.go
++++ b/src/go/constant/value.go
+@@ -276,10 +276,10 @@ func smallRat(x *big.Float) bool {
+ // MakeUnknown returns the Unknown value.
+ func MakeUnknown() Value { return unknownVal{} }
+
+-// MakeBool returns the Bool value for x.
++// MakeBool returns the Bool value for b.
+ func MakeBool(b bool) Value { return boolVal(b) }
+
+-// MakeString returns the String value for x.
++// MakeString returns the String value for s.
+ func MakeString(s string) Value { return stringVal(s) }
+
+ // MakeInt64 returns the Int value for x.
+diff --git a/src/go/doc/comment.go b/src/go/doc/comment.go
+index f414ca4..5631539 100644
+--- a/src/go/doc/comment.go
++++ b/src/go/doc/comment.go
+@@ -225,7 +225,7 @@ func heading(line string) string {
+ }
+
+ // exclude lines with illegal characters
+- if strings.IndexAny(line, ",.;:!?+*/=()[]{}_^°&§~%#@<\">\\") >= 0 {
++ if strings.ContainsAny(line, ",.;:!?+*/=()[]{}_^°&§~%#@<\">\\") {
+ return ""
+ }
+
+diff --git a/src/go/internal/gcimporter/gcimporter.go b/src/go/internal/gcimporter/gcimporter.go
+index d70ec08..052277f 100644
+--- a/src/go/internal/gcimporter/gcimporter.go
++++ b/src/go/internal/gcimporter/gcimporter.go
+@@ -385,7 +385,7 @@ func (p *parser) getPkg(id, name string) *types.Package {
+ if pname := pkg.Name(); pname == "" {
+ pkg.SetName(name)
+ } else if pname != name {
+- p.errorf("%s package name mismatch: %s (given) vs %s (expected)", pname, name)
++ p.errorf("%s package name mismatch: %s (given) vs %s (expected)", id, pname, name)
+ }
+ }
+ return pkg
+diff --git a/src/go/types/universe.go b/src/go/types/universe.go
+index 40185c1..cc3bd5a 100644
+--- a/src/go/types/universe.go
++++ b/src/go/types/universe.go
+@@ -196,7 +196,7 @@ func init() {
+ //
+ func def(obj Object) {
+ name := obj.Name()
+- if strings.Index(name, " ") >= 0 {
++ if strings.Contains(name, " ") {
+ return // nothing to do
+ }
+ // fix Obj link for named types
diff --git a/src/hash/crc32/crc32_generic.go b/src/hash/crc32/crc32_generic.go
index 8fc11a7..25f2d55 100644
--- a/src/hash/crc32/crc32_generic.go
@@ -21724,7 +32641,7 @@ index 0000000..d435f71
+const randomTrap uintptr = 349
diff --git a/src/math/big/arith_s390x.s b/src/math/big/arith_s390x.s
new file mode 100644
-index 0000000..d296d64
+index 0000000..35ed863
--- /dev/null
+++ b/src/math/big/arith_s390x.s
@@ -0,0 +1,574 @@
@@ -21771,7 +32688,7 @@ index 0000000..d296d64
+
+ // s/JL/JMP/ below to disable the unrolled loop
+ SUB $4, R3 // n -= 4
-+ BLT V1 // if n < 0 goto V1
++ BLT v1 // if n < 0 goto v1
+
+U1: // n >= 0
+ // regular loop body unrolled 4x
@@ -21801,7 +32718,7 @@ index 0000000..d296d64
+ SUB $4, R3 // n -= 4
+ BGE U1 // if n >= 0 goto U1
+
-+V1: ADD $4, R3 // n += 4
++v1: ADD $4, R3 // n += 4
+ BLE E1 // if n <= 0 goto E1
+
+L1: // n > 0
@@ -21837,7 +32754,7 @@ index 0000000..d296d64
+
+ // s/JL/JMP/ below to disable the unrolled loop
+ SUB $4, R3 // n -= 4
-+ BLT V1 // if n < 0 goto V1
++ BLT v1 // if n < 0 goto v1
+
+U1: // n >= 0
+ // regular loop body unrolled 4x
@@ -21867,7 +32784,7 @@ index 0000000..d296d64
+ SUB $4, R3 // n -= 4
+ BGE U1 // if n >= 0 goto U1
+
-+V1: ADD $4, R3 // n += 4
++v1: ADD $4, R3 // n += 4
+ BLE E1 // if n <= 0 goto E1
+
+L1: // n > 0
@@ -21901,7 +32818,7 @@ index 0000000..d296d64
+
+ // s/JL/JMP/ below to disable the unrolled loop
+ SUB $4, R3 // n -= 4
-+ BLT V4 // if n < 4 goto V4
++ BLT v4 // if n < 4 goto v4
+
+U4: // n >= 0
+ // regular loop body unrolled 4x
@@ -21925,7 +32842,7 @@ index 0000000..d296d64
+ SUB $4, R3 // n -= 4
+ BGE U4 // if n >= 0 goto U4
+
-+V4: ADD $4, R3 // n += 4
++v4: ADD $4, R3 // n += 4
+ BLE E4 // if n <= 0 goto E4
+
+L4: // n > 0
@@ -21957,7 +32874,7 @@ index 0000000..d296d64
+
+ // s/JL/JMP/ below to disable the unrolled loop
+ SUB $4, R3 // n -= 4
-+ BLT V4 // if n < 4 goto V4
++ BLT v4 // if n < 4 goto v4
+
+U4: // n >= 0
+ // regular loop body unrolled 4x
@@ -21980,7 +32897,7 @@ index 0000000..d296d64
+ SUB $4, R3 // n -= 4
+ BGE U4 // if n >= 0 goto U4
+
-+V4: ADD $4, R3 // n += 4
++v4: ADD $4, R3 // n += 4
+ BLE E4 // if n <= 0 goto E4
+
+L4: // n > 0
@@ -22302,6 +33219,28 @@ index 0000000..d296d64
+ SUB R2, R3
+ MOVD R3, n+8(FP)
+ RET
+diff --git a/src/math/big/ratconv.go b/src/math/big/ratconv.go
+index 4566ff4..57df124 100644
+--- a/src/math/big/ratconv.go
++++ b/src/math/big/ratconv.go
+@@ -15,7 +15,7 @@ import (
+ )
+
+ func ratTok(ch rune) bool {
+- return strings.IndexRune("+-/0123456789.eE", ch) >= 0
++ return strings.ContainsRune("+-/0123456789.eE", ch)
+ }
+
+ // Scan is a support routine for fmt.Scanner. It accepts the formats
+@@ -25,7 +25,7 @@ func (z *Rat) Scan(s fmt.ScanState, ch rune) error {
+ if err != nil {
+ return err
+ }
+- if strings.IndexRune("efgEFGv", ch) < 0 {
++ if !strings.ContainsRune("efgEFGv", ch) {
+ return errors.New("Rat.Scan: invalid verb")
+ }
+ if _, ok := z.SetString(string(tok)); !ok {
diff --git a/src/math/dim_s390x.s b/src/math/dim_s390x.s
new file mode 100644
index 0000000..55c8ac1
@@ -22541,6 +33480,228 @@ index 0000000..305480e
+
+TEXT ·Tan(SB),NOSPLIT,$0
+ BR ·tan(SB)
+diff --git a/src/mime/grammar.go b/src/mime/grammar.go
+index 31b66e8..6a6f71d 100644
+--- a/src/mime/grammar.go
++++ b/src/mime/grammar.go
+@@ -11,7 +11,7 @@ import (
+ // isTSpecial reports whether rune is in 'tspecials' as defined by RFC
+ // 1521 and RFC 2045.
+ func isTSpecial(r rune) bool {
+- return strings.IndexRune(`()<>@,;:\"/[]?=`, r) != -1
++ return strings.ContainsRune(`()<>@,;:\"/[]?=`, r)
+ }
+
+ // isTokenChar reports whether rune is in 'token' as defined by RFC
+diff --git a/src/net/dnsmsg.go b/src/net/dnsmsg.go
+index 93078fe..2ec4c8c 100644
+--- a/src/net/dnsmsg.go
++++ b/src/net/dnsmsg.go
+@@ -406,6 +406,13 @@ func packDomainName(s string, msg []byte, off int) (off1 int, ok bool) {
+ s += "."
+ }
+
++ // Allow root domain.
++ if s == "." {
++ msg[off] = 0
++ off++
++ return off, true
++ }
++
+ // Each dot ends a segment of the name.
+ // We trade each dot byte for a length byte.
+ // There is also a trailing zero.
+@@ -422,8 +429,13 @@ func packDomainName(s string, msg []byte, off int) (off1 int, ok bool) {
+ if i-begin >= 1<<6 { // top two bits of length must be clear
+ return len(msg), false
+ }
++ if i-begin == 0 {
++ return len(msg), false
++ }
++
+ msg[off] = byte(i - begin)
+ off++
++
+ for j := begin; j < i; j++ {
+ msg[off] = s[j]
+ off++
+@@ -494,6 +506,9 @@ Loop:
+ return "", len(msg), false
+ }
+ }
++ if len(s) == 0 {
++ s = "."
++ }
+ if ptr == 0 {
+ off1 = off
+ }
+@@ -803,20 +818,32 @@ func (dns *dnsMsg) Pack() (msg []byte, ok bool) {
+ // Pack it in: header and then the pieces.
+ off := 0
+ off, ok = packStruct(&dh, msg, off)
++ if !ok {
++ return nil, false
++ }
+ for i := 0; i < len(question); i++ {
+ off, ok = packStruct(&question[i], msg, off)
++ if !ok {
++ return nil, false
++ }
+ }
+ for i := 0; i < len(answer); i++ {
+ off, ok = packRR(answer[i], msg, off)
++ if !ok {
++ return nil, false
++ }
+ }
+ for i := 0; i < len(ns); i++ {
+ off, ok = packRR(ns[i], msg, off)
++ if !ok {
++ return nil, false
++ }
+ }
+ for i := 0; i < len(extra); i++ {
+ off, ok = packRR(extra[i], msg, off)
+- }
+- if !ok {
+- return nil, false
++ if !ok {
++ return nil, false
++ }
+ }
+ return msg[0:off], true
+ }
+@@ -848,6 +875,9 @@ func (dns *dnsMsg) Unpack(msg []byte) bool {
+
+ for i := 0; i < len(dns.question); i++ {
+ off, ok = unpackStruct(&dns.question[i], msg, off)
++ if !ok {
++ return false
++ }
+ }
+ for i := 0; i < int(dh.Ancount); i++ {
+ rec, off, ok = unpackRR(msg, off)
+diff --git a/src/net/dnsmsg_test.go b/src/net/dnsmsg_test.go
+index 1078d77..339fb83 100644
+--- a/src/net/dnsmsg_test.go
++++ b/src/net/dnsmsg_test.go
+@@ -10,6 +10,103 @@ import (
+ "testing"
+ )
+
++func TestStructPackUnpack(t *testing.T) {
++ want := dnsQuestion{
++ Name: ".",
++ Qtype: dnsTypeA,
++ Qclass: dnsClassINET,
++ }
++ buf := make([]byte, 50)
++ n, ok := packStruct(&want, buf, 0)
++ if !ok {
++ t.Fatal("packing failed")
++ }
++ buf = buf[:n]
++ got := dnsQuestion{}
++ n, ok = unpackStruct(&got, buf, 0)
++ if !ok {
++ t.Fatal("unpacking failed")
++ }
++ if n != len(buf) {
++ t.Error("unpacked different amount than packed: got n = %d, want = %d", n, len(buf))
++ }
++ if !reflect.DeepEqual(got, want) {
++ t.Errorf("got = %+v, want = %+v", got, want)
++ }
++}
++
++func TestDomainNamePackUnpack(t *testing.T) {
++ tests := []struct {
++ in string
++ want string
++ ok bool
++ }{
++ {"", ".", true},
++ {".", ".", true},
++ {"google..com", "", false},
++ {"google.com", "google.com.", true},
++ {"google..com.", "", false},
++ {"google.com.", "google.com.", true},
++ {".google.com.", "", false},
++ {"www..google.com.", "", false},
++ {"www.google.com.", "www.google.com.", true},
++ }
++
++ for _, test := range tests {
++ buf := make([]byte, 30)
++ n, ok := packDomainName(test.in, buf, 0)
++ if ok != test.ok {
++ t.Errorf("packing of %s: got ok = %t, want = %t", test.in, ok, test.ok)
++ continue
++ }
++ if !test.ok {
++ continue
++ }
++ buf = buf[:n]
++ got, n, ok := unpackDomainName(buf, 0)
++ if !ok {
++ t.Errorf("unpacking for %s failed", test.in)
++ continue
++ }
++ if n != len(buf) {
++ t.Error(
++ "unpacked different amount than packed for %s: got n = %d, want = %d",
++ test.in,
++ n,
++ len(buf),
++ )
++ }
++ if got != test.want {
++ t.Errorf("unpacking packing of %s: got = %s, want = %s", test.in, got, test.want)
++ }
++ }
++}
++
++func TestDNSPackUnpack(t *testing.T) {
++ want := dnsMsg{
++ question: []dnsQuestion{{
++ Name: ".",
++ Qtype: dnsTypeAAAA,
++ Qclass: dnsClassINET,
++ }},
++ answer: []dnsRR{},
++ ns: []dnsRR{},
++ extra: []dnsRR{},
++ }
++ b, ok := want.Pack()
++ if !ok {
++ t.Fatal("packing failed")
++ }
++ var got dnsMsg
++ ok = got.Unpack(b)
++ if !ok {
++ t.Fatal("unpacking failed")
++ }
++ if !reflect.DeepEqual(got, want) {
++ t.Errorf("got = %+v, want = %+v", got, want)
++ }
++}
++
+ func TestDNSParseSRVReply(t *testing.T) {
+ data, err := hex.DecodeString(dnsSRVReply)
+ if err != nil {
+diff --git a/src/net/http/fs.go b/src/net/http/fs.go
+index f61c138..8a5b8bb 100644
+--- a/src/net/http/fs.go
++++ b/src/net/http/fs.go
+@@ -34,7 +34,7 @@ import (
+ type Dir string
+
+ func (d Dir) Open(name string) (File, error) {
+- if filepath.Separator != '/' && strings.IndexRune(name, filepath.Separator) >= 0 ||
++ if filepath.Separator != '/' && strings.ContainsRune(name, filepath.Separator) ||
+ strings.Contains(name, "\x00") {
+ return nil, errors.New("http: invalid character in file path")
+ }
diff --git a/src/net/http/fs_test.go b/src/net/http/fs_test.go
index 69d7806..9799ec7 100644
--- a/src/net/http/fs_test.go
@@ -22558,6 +33719,43 @@ index 69d7806..9799ec7 100644
syscalls = "sendfile"
}
+diff --git a/src/net/http/transport.go b/src/net/http/transport.go
+index baf71d5..1e3ea11 100644
+--- a/src/net/http/transport.go
++++ b/src/net/http/transport.go
+@@ -176,9 +176,13 @@ func (t *Transport) onceSetNextProtoDefaults() {
+ // Issue 14275.
+ return
+ }
+- if t.ExpectContinueTimeout != 0 {
+- // Unsupported in http2, so disable http2 for now.
+- // Issue 13851.
++ if t.ExpectContinueTimeout != 0 && t != DefaultTransport {
++ // ExpectContinueTimeout is unsupported in http2, so
++ // if they explicitly asked for it (as opposed to just
++ // using the DefaultTransport, which sets it), then
++ // disable http2 for now.
++ //
++ // Issue 13851. (and changed in Issue 14391)
+ return
+ }
+ t2, err := http2configureTransport(t)
+diff --git a/src/net/http/transport_test.go b/src/net/http/transport_test.go
+index 0c901b3..d9da078 100644
+--- a/src/net/http/transport_test.go
++++ b/src/net/http/transport_test.go
+@@ -2888,6 +2888,11 @@ func TestTransportAutomaticHTTP2(t *testing.T) {
+ testTransportAutoHTTP(t, &Transport{}, true)
+ }
+
++// golang.org/issue/14391: also check DefaultTransport
++func TestTransportAutomaticHTTP2_DefaultTransport(t *testing.T) {
++ testTransportAutoHTTP(t, DefaultTransport.(*Transport), true)
++}
++
+ func TestTransportAutomaticHTTP2_TLSNextProto(t *testing.T) {
+ testTransportAutoHTTP(t, &Transport{
+ TLSNextProto: make(map[string]func(string, *tls.Conn) RoundTripper),
diff --git a/src/net/lookup_test.go b/src/net/lookup_test.go
index 439496a..f8f69c7 100644
--- a/src/net/lookup_test.go
@@ -22574,6 +33772,100 @@ index 439496a..f8f69c7 100644
for _, tt := range lookupPortTests {
if port, err := LookupPort(tt.network, tt.name); port != tt.port || (err == nil) != tt.ok {
t.Errorf("LookupPort(%q, %q) = %d, %v; want %d", tt.network, tt.name, port, err, tt.port)
+diff --git a/src/net/rpc/server_test.go b/src/net/rpc/server_test.go
+index 8871c88..cf171ac 100644
+--- a/src/net/rpc/server_test.go
++++ b/src/net/rpc/server_test.go
+@@ -183,7 +183,7 @@ func testRPC(t *testing.T, addr string) {
+ err = client.Call("Arith.Unknown", args, reply)
+ if err == nil {
+ t.Error("expected error calling unknown service")
+- } else if strings.Index(err.Error(), "method") < 0 {
++ } else if !strings.Contains(err.Error(), "method") {
+ t.Error("expected error about method; got", err)
+ }
+
+@@ -226,7 +226,7 @@ func testRPC(t *testing.T, addr string) {
+ err = client.Call("Arith.Add", reply, reply) // args, reply would be the correct thing to use
+ if err == nil {
+ t.Error("expected error calling Arith.Add with wrong arg type")
+- } else if strings.Index(err.Error(), "type") < 0 {
++ } else if !strings.Contains(err.Error(), "type") {
+ t.Error("expected error about type; got", err)
+ }
+
+diff --git a/src/net/url/url.go b/src/net/url/url.go
+index 1a93e34..b7e25ec 100644
+--- a/src/net/url/url.go
++++ b/src/net/url/url.go
+@@ -511,7 +511,7 @@ func parseAuthority(authority string) (user *Userinfo, host string, err error) {
+ return nil, host, nil
+ }
+ userinfo := authority[:i]
+- if strings.Index(userinfo, ":") < 0 {
++ if !strings.Contains(userinfo, ":") {
+ if userinfo, err = unescape(userinfo, encodeUserPassword); err != nil {
+ return nil, "", err
+ }
+diff --git a/src/os/exec/lp_windows.go b/src/os/exec/lp_windows.go
+index c3efd67..0b0712d 100644
+--- a/src/os/exec/lp_windows.go
++++ b/src/os/exec/lp_windows.go
+@@ -70,7 +70,7 @@ func LookPath(file string) (f string, err error) {
+ }
+ exts = append(exts, e)
+ }
+- if strings.IndexAny(file, `:\/`) != -1 {
++ if strings.ContainsAny(file, `:\/`) {
+ if f, err = findExecutable(file, exts); err == nil {
+ return
+ }
+diff --git a/src/path/filepath/match.go b/src/path/filepath/match.go
+index 89f16de..d64bf84 100644
+--- a/src/path/filepath/match.go
++++ b/src/path/filepath/match.go
+@@ -49,7 +49,7 @@ Pattern:
+ star, chunk, pattern = scanChunk(pattern)
+ if star && chunk == "" {
+ // Trailing * matches rest of string unless it has a /.
+- return strings.Index(name, string(Separator)) < 0, nil
++ return !strings.Contains(name, string(Separator)), nil
+ }
+ // Look for match at current position.
+ t, ok, err := matchChunk(chunk, name)
+@@ -305,5 +305,5 @@ func glob(dir, pattern string, matches []string) (m []string, e error) {
+ // recognized by Match.
+ func hasMeta(path string) bool {
+ // TODO(niemeyer): Should other magic characters be added here?
+- return strings.IndexAny(path, "*?[") >= 0
++ return strings.ContainsAny(path, "*?[")
+ }
+diff --git a/src/path/filepath/match_test.go b/src/path/filepath/match_test.go
+index 0edbfc7..d8bab7f 100644
+--- a/src/path/filepath/match_test.go
++++ b/src/path/filepath/match_test.go
+@@ -88,7 +88,7 @@ func TestMatch(t *testing.T) {
+ pattern := tt.pattern
+ s := tt.s
+ if runtime.GOOS == "windows" {
+- if strings.Index(pattern, "\\") >= 0 {
++ if strings.Contains(pattern, "\\") {
+ // no escape allowed on windows.
+ continue
+ }
+diff --git a/src/path/match.go b/src/path/match.go
+index 75dd3b3..8d9aa51 100644
+--- a/src/path/match.go
++++ b/src/path/match.go
+@@ -43,7 +43,7 @@ Pattern:
+ star, chunk, pattern = scanChunk(pattern)
+ if star && chunk == "" {
+ // Trailing * matches rest of string unless it has a /.
+- return strings.Index(name, "/") < 0, nil
++ return !strings.Contains(name, "/"), nil
+ }
+ // Look for match at current position.
+ t, ok, err := matchChunk(chunk, name)
diff --git a/src/reflect/asm_s390x.s b/src/reflect/asm_s390x.s
new file mode 100644
index 0000000..4810d46
@@ -22610,12 +33902,38 @@ index 0000000..4810d46
+ MOVD R3, 16(R15)
+ BL ·callMethod(SB)
+ RET
+diff --git a/src/regexp/regexp.go b/src/regexp/regexp.go
+index d7d0edb..42ae6e1 100644
+--- a/src/regexp/regexp.go
++++ b/src/regexp/regexp.go
+@@ -454,7 +454,7 @@ func Match(pattern string, b []byte) (matched bool, err error) {
+ // in Expand, so for instance $1 represents the text of the first submatch.
+ func (re *Regexp) ReplaceAllString(src, repl string) string {
+ n := 2
+- if strings.Index(repl, "$") >= 0 {
++ if strings.Contains(repl, "$") {
+ n = 2 * (re.numSubexp + 1)
+ }
+ b := re.replaceAll(nil, src, n, func(dst []byte, match []int) []byte {
+diff --git a/src/regexp/syntax/regexp.go b/src/regexp/syntax/regexp.go
+index 75822cf..ca57240 100644
+--- a/src/regexp/syntax/regexp.go
++++ b/src/regexp/syntax/regexp.go
+@@ -252,7 +252,7 @@ const meta = `\.+*?()|[]{}^$`
+
+ func escape(b *bytes.Buffer, r rune, force bool) {
+ if unicode.IsPrint(r) {
+- if strings.IndexRune(meta, r) >= 0 || force {
++ if strings.ContainsRune(meta, r) || force {
+ b.WriteRune('\\')
+ }
+ b.WriteRune(r)
diff --git a/src/runtime/asm_s390x.s b/src/runtime/asm_s390x.s
new file mode 100644
-index 0000000..861747e
+index 0000000..3390dc8
--- /dev/null
+++ b/src/runtime/asm_s390x.s
-@@ -0,0 +1,1182 @@
+@@ -0,0 +1,1122 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
@@ -22625,6 +33943,25 @@ index 0000000..861747e
+#include "funcdata.h"
+#include "textflag.h"
+
++DATA runtime·vectorfacility+0x00(SB)/4, $0
++GLOBL runtime·vectorfacility(SB), NOPTR, $4
++
++TEXT runtime·checkvectorfacility(SB),NOSPLIT,$24-0
++ MOVD $2, R0
++ MOVD $x-24(SP), R1
++ // STFLE 0(R1)
++ WORD $0xB2B01000
++ MOVBZ z-8(SP), R1
++ AND $0x40, R1
++ BNE setvector
++ MOVD $0, R0
++ RET
++setvector:
++ MOVD $1, R1
++ MOVBZ R1, runtime·vectorfacility(SB)
++ MOVD $0, R0
++ RET
++
+TEXT runtime·rt0_go(SB),NOSPLIT,$0
+ // R2 = argc; R3 = argv; R11 = temp; R13 = g; R15 = stack pointer
+ // C TLS base pointer in AR0:AR1
@@ -22686,6 +34023,9 @@ index 0000000..861747e
+ BL runtime·osinit(SB)
+ BL runtime·schedinit(SB)
+
++ // check and set the vectorfacility
++ BL runtime·checkvectorfacility(SB)
++
+ // create a new goroutine to start program
+ MOVD $runtime·mainPC(SB), R2 // entry
+ SUB $24, R15
@@ -23314,9 +34654,6 @@ index 0000000..861747e
+ MOVW (R0), R0
+ UNDEF
+
-+#define TBRL 268
-+#define TBRU 269 /* Time base Upper/Lower */
-+
+// int64 runtime·cputicks(void)
+TEXT runtime·cputicks(SB),NOSPLIT,$0-8
+ // The TOD clock on s390 counts from the year 1900 in ~250ps intervals.
@@ -23357,215 +34694,113 @@ index 0000000..861747e
+TEXT runtime·aeshashstr(SB),NOSPLIT|NOFRAME,$0-0
+ MOVW (R0), R15
+
-+TEXT runtime·clc(SB),NOSPLIT,$0-0
-+ CLC $1, 0(R3), 0(R4)
-+ RET
-+
+TEXT runtime·memeq(SB),NOSPLIT|NOFRAME,$0-25
+ MOVD a+0(FP), R3
-+ MOVD b+8(FP), R4
-+ CMPBNE R3, R4, 4(PC)
-+ MOVD $1, R5
-+ MOVB R5, ret+24(FP)
-+ RET
-+ MOVD size+16(FP), R5
-+loop:
-+ CMPBEQ R5, $0, equal
-+ CMP R5, $256
-+ BLT tail
-+ CLC $256, 0(R3), 0(R4)
-+ BNE notequal
-+ SUB $256, R5
-+ ADD $256, R3
-+ ADD $256, R4
-+ BR loop
-+tail:
-+ SUB $1, R5
-+ EXRL $runtime·clc(SB), R5
-+ BEQ equal
-+ MOVB R0, ret+24(FP)
-+ RET
-+equal:
-+ MOVD $1, R5
-+ MOVB R5, ret+24(FP)
-+ RET
-+notequal:
-+ MOVB R0, ret+24(FP)
-+ RET
++ MOVD b+8(FP), R5
++ MOVD size+16(FP), R6
++ LA ret+24(FP), R7
++ BR runtime·memeqbody(SB)
+
+// memequal_varlen(a, b unsafe.Pointer) bool
-+TEXT runtime·memequal_varlen(SB),NOSPLIT,$40-17
++TEXT runtime·memequal_varlen(SB),NOSPLIT|NOFRAME,$0-17
+ MOVD a+0(FP), R3
-+ MOVD b+8(FP), R4
-+ CMPBEQ R3, R4, eq
-+ MOVD 8(R12), R5 // compiler stores size at offset 8 in the closure
-+ MOVD R3, 8(R15)
-+ MOVD R4, 16(R15)
-+ MOVD R5, 24(R15)
-+ BL runtime·memeq(SB)
-+ MOVBZ 32(R15), R3
-+ MOVB R3, ret+16(FP)
-+ RET
-+eq:
-+ MOVD $1, R3
-+ MOVB R3, ret+16(FP)
-+ RET
++ MOVD b+8(FP), R5
++ MOVD 8(R12), R6 // compiler stores size at offset 8 in the closure
++ LA ret+16(FP), R7
++ BR runtime·memeqbody(SB)
+
+// eqstring tests whether two strings are equal.
+// The compiler guarantees that strings passed
+// to eqstring have equal length.
+// See runtime_test.go:eqstring_generic for
+// equivalent Go code.
-+TEXT runtime·eqstring(SB),NOSPLIT,$0-33
++TEXT runtime·eqstring(SB),NOSPLIT|NOFRAME,$0-33
+ MOVD s1str+0(FP), R3
-+ MOVD s2str+16(FP), R4
-+ CMPBNE R3, R4, 4(PC)
-+ MOVD $1, R5
-+ MOVB R5, ret+32(FP)
++ MOVD s1len+8(FP), R6
++ MOVD s2str+16(FP), R5
++ LA ret+32(FP), R7
++ BR runtime·memeqbody(SB)
++
++TEXT bytes·Equal(SB),NOSPLIT|NOFRAME,$0-49
++ MOVD a_len+8(FP), R2
++ MOVD b_len+32(FP), R6
++ MOVD a+0(FP), R3
++ MOVD b+24(FP), R5
++ LA ret+48(FP), R7
++ CMPBNE R2, R6, notequal
++ BR runtime·memeqbody(SB)
++notequal:
++ MOVB $0, ret+48(FP)
+ RET
-+ MOVD s1len+8(FP), R5
++
++// input:
++// R3 = a
++// R5 = b
++// R6 = len
++// R7 = address of output byte (stores 0 or 1 here)
++// a and b have the same length
++TEXT runtime·memeqbody(SB),NOSPLIT|NOFRAME,$0-0
++ CMPBEQ R3, R5, equal
+loop:
-+ CMPBEQ R5, $0, equal
-+ CMP R5, $256
++ CMPBEQ R6, $0, equal
++ CMPBLT R6, $32, tiny
++ CMP R6, $256
+ BLT tail
-+ CLC $256, 0(R3), 0(R4)
++ CLC $256, 0(R3), 0(R5)
+ BNE notequal
-+ SUB $256, R5
-+ ADD $256, R3
-+ ADD $256, R4
++ SUB $256, R6
++ LA 256(R3), R3
++ LA 256(R5), R5
+ BR loop
+tail:
-+ SUB $1, R5
-+ EXRL $runtime·clc(SB), R5
++ SUB $1, R6, R8
++ EXRL $runtime·memeqbodyclc(SB), R8
+ BEQ equal
-+ MOVB R0, ret+32(FP)
-+ RET
-+equal:
-+ MOVD $1, R5
-+ MOVB R5, ret+32(FP)
-+ RET
+notequal:
-+ MOVB R0, ret+32(FP)
-+ RET
-+
-+// TODO: share code with memeq?
-+TEXT bytes·Equal(SB),NOSPLIT,$0-49
-+ MOVD a_len+8(FP), R5
-+ MOVD b_len+32(FP), R6
-+ CMPBNE R5, R6, notequal
-+ MOVD a+0(FP), R3
-+ MOVD b+24(FP), R4
-+ CMPBLE R5, $32, tiny
-+ CMP R5, $256
-+ BGT loop
-+tail:
-+ SUB $1, R5
-+ EXRL $runtime·clc(SB), R5
-+ BEQ equal
-+ MOVB R0, ret+48(FP)
++ MOVB $0, 0(R7)
+ RET
-+loop:
-+ CLC $256, 0(R3), 0(R4)
-+ BNE notequal
-+ SUB $256, R5
-+ ADD $256, R3
-+ ADD $256, R4
-+ CMP R5, $256
-+ BGE loop
-+ CMPBNE R5, $0, tail
+equal:
-+ MOVD $1, R5
-+ MOVB R5, ret+48(FP)
-+ RET
-+notequal:
-+ MOVB R0, ret+48(FP)
++ MOVB $1, 0(R7)
+ RET
+tiny:
-+ CMPBLT R5, $16, lt16
-+ MOVD 0(R3), R6
-+ MOVD 0(R4), R7
-+ CMPBNE R6, R7, notequal
-+ MOVD 8(R3), R6
-+ MOVD 8(R4), R7
-+ CMPBNE R6, R7, notequal
-+ ADD $16, R3
-+ ADD $16, R4
-+ SUB $16, R5
++ MOVD $0, R2
++ CMPBLT R6, $16, lt16
++ MOVD 0(R3), R8
++ MOVD 0(R5), R9
++ CMPBNE R8, R9, notequal
++ MOVD 8(R3), R8
++ MOVD 8(R5), R9
++ CMPBNE R8, R9, notequal
++ LA 16(R2), R2
++ SUB $16, R6
+lt16:
-+ CMPBLT R5, $8, lt8
-+ MOVD 0(R3), R6
-+ MOVD 0(R4), R7
-+ CMPBNE R6, R7, notequal
-+ ADD $8, R3
-+ ADD $8, R4
-+ SUB $8, R5
++ CMPBLT R6, $8, lt8
++ MOVD 0(R3)(R2*1), R8
++ MOVD 0(R5)(R2*1), R9
++ CMPBNE R8, R9, notequal
++ LA 8(R2), R2
++ SUB $8, R6
+lt8:
-+ CMPBLT R5, $4, lt4
-+ MOVWZ 0(R3), R6
-+ MOVWZ 0(R4), R7
-+ CMPBNE R6, R7, notequal
-+ ADD $4, R3
-+ ADD $4, R4
-+ SUB $4, R5
++ CMPBLT R6, $4, lt4
++ MOVWZ 0(R3)(R2*1), R8
++ MOVWZ 0(R5)(R2*1), R9
++ CMPBNE R8, R9, notequal
++ LA 4(R2), R2
++ SUB $4, R6
+lt4:
+#define CHECK(n) \
-+ CMPBEQ R5, $n, equal \
-+ MOVB n(R3), R6 \
-+ MOVB n(R4), R7 \
-+ CMP R6, R7 \
-+ BNE notequal
++ CMPBEQ R6, $n, equal \
++ MOVB n(R3)(R2*1), R8 \
++ MOVB n(R5)(R2*1), R9 \
++ CMPBNE R8, R9, notequal
+ CHECK(0)
+ CHECK(1)
+ CHECK(2)
+ CHECK(3)
+ BR equal
+
-+TEXT bytes·IndexByte(SB),NOSPLIT,$0-40
-+ MOVD s+0(FP), R3
-+ MOVD s_len+8(FP), R4
-+ MOVBZ c+24(FP), R5 // byte to find
-+ CMP R4, $0
-+ BEQ notfound
-+ MOVD R3, R6 // store base for later
-+ ADD R3, R4 // calculate end marker
-+ MOVBZ R5, R0 // c needs to be in R0, leave until last minute as currently R0 is expected to be 0
-+loop:
-+ WORD $0xB25E0043 // srst %r4, %r3 (search the range [R3, R4))
-+ BVS loop // interrupted - continue
-+ BGT notfound
-+found:
-+ XOR R0, R0 // reset R0
-+ SUB R6, R4 // remove base
-+ MOVD R4, ret+32(FP)
-+ RET
-+notfound:
-+ XOR R0, R0 // reset R0
-+ MOVD $-1, R1
-+ MOVD R1, ret+32(FP)
-+ RET
-+
-+TEXT strings·IndexByte(SB),NOSPLIT,$0-32
-+ MOVD p+0(FP), R3
-+ MOVD b_len+8(FP), R4
-+ MOVBZ c+16(FP), R5 // byte to find
-+ CMP R4, $0
-+ BEQ notfound
-+ MOVD R3, R6 // store base for later
-+ ADD R3, R4 // calculate end marker
-+ MOVBZ R5, R0 // c needs to be in R0, leave until last minute as currently R0 is expected to be 0
-+loop:
-+ WORD $0xB25E0043 // srst %r4, %r3 (search the range [R3, R4))
-+ BVS loop // interrupted - continue
-+ BGT notfound
-+found:
-+ XOR R0, R0 // reset R0
-+ SUB R6, R4 // remove base
-+ MOVD R4, ret+24(FP)
-+ RET
-+notfound:
-+ XOR R0, R0 // reset R0
-+ MOVD $-1, R1
-+ MOVD R1, ret+24(FP)
++TEXT runtime·memeqbodyclc(SB),NOSPLIT|NOFRAME,$0-0
++ CLC $1, 0(R3), 0(R5)
+ RET
+
+TEXT runtime·fastrand1(SB), NOSPLIT, $0-4
@@ -23579,6 +34814,105 @@ index 0000000..861747e
+ MOVW R3, ret+0(FP)
+ RET
+
++TEXT bytes·IndexByte(SB),NOSPLIT,$0-40
++ MOVD s+0(FP), R3 // s => R3
++ MOVD s_len+8(FP), R4 // s_len => R4
++ MOVBZ c+24(FP), R5 // c => R5
++ MOVD $ret+32(FP), R2 // &ret => R9
++ BR runtime·indexbytebody(SB)
++
++TEXT strings·IndexByte(SB),NOSPLIT,$0-32
++ MOVD s+0(FP), R3 // s => R3
++ MOVD s_len+8(FP), R4 // s_len => R4
++ MOVBZ c+16(FP), R5 // c => R5
++ MOVD $ret+24(FP), R2 // &ret => R9
++ BR runtime·indexbytebody(SB)
++
++// input:
++// R3: s
++// R4: s_len
++// R5: c -- byte sought
++// R2: &ret -- address to put index into
++TEXT runtime·indexbytebody(SB),NOSPLIT,$0
++ CMPBEQ R4, $0, notfound
++ MOVD R3, R6 // store base for later
++ ADD R3, R4, R8 // the address after the end of the string
++ //if the length is small, use loop; otherwise, use vector or srst search
++ CMPBGE R4, $16, large
++
++residual:
++ CMPBEQ R3, R8, notfound
++ MOVBZ 0(R3), R7
++ LA 1(R3), R3
++ CMPBNE R7, R5, residual
++
++found:
++ SUB R6, R3
++ SUB $1, R3
++ MOVD R3, 0(R2)
++ RET
++
++notfound:
++ MOVD $-1, 0(R2)
++ RET
++
++large:
++ MOVBZ runtime·vectorfacility(SB), R1
++ CMPBEQ R1, $1, vectorimpl // vectorfacility = 1, vector supported
++
++srstimpl: // vectorfacility == 0, not support vector
++ MOVBZ R5, R0 // c needs to be in R0, leave until last minute as currently R0 is expected to be 0
++srstloop:
++ WORD $0xB25E0083 // srst %r8, %r3 (search the range [R3, R8))
++ BVS srstloop // interrupted - continue
++ BGT notfoundr0
++foundr0:
++ XOR R0, R0 // reset R0
++ SUB R6, R8 // remove base
++ MOVD R8, 0(R2)
++ RET
++notfoundr0:
++ XOR R0, R0 // reset R0
++ MOVD $-1, 0(R2)
++ RET
++
++vectorimpl:
++ //if the address is not 16byte aligned, use loop for the header
++ AND $15, R3, R8
++ CMPBGT R8, $0, notaligned
++
++aligned:
++ ADD R6, R4, R8
++ AND $-16, R8, R7
++ // replicate c across V17
++ VLVGB $0, R5, V19
++ VREPB $0, V19, V17
++
++vectorloop:
++ CMPBGE R3, R7, residual
++ VL 0(R3), V16 // load string to be searched into V16
++ ADD $16, R3
++ VFEEBS V16, V17, V18 // search V17 in V16 and set conditional code accordingly
++ BVS vectorloop
++
++ // when vector search found c in the string
++ VLGVB $7, V18, R7 // load 7th element of V18 containing index into R7
++ SUB $16, R3
++ SUB R6, R3
++ ADD R3, R7
++ MOVD R7, 0(R2)
++ RET
++
++notaligned:
++ AND $-16, R3, R8
++ ADD $16, R8
++notalignedloop:
++ CMPBEQ R3, R8, aligned
++ MOVBZ 0(R3), R7
++ LA 1(R3), R3
++ CMPBNE R7, R5, notalignedloop
++ BR found
++
+TEXT runtime·return0(SB), NOSPLIT, $0
+ MOVW $0, R3
+ RET
@@ -23630,106 +34964,39 @@ index 0000000..861747e
+ SYNC
+ RET
+
-+TEXT runtime·cmpstring(SB),NOSPLIT,$0-40
++TEXT runtime·cmpstring(SB),NOSPLIT|NOFRAME,$0-40
+ MOVD s1_base+0(FP), R3
+ MOVD s1_len+8(FP), R4
+ MOVD s2_base+16(FP), R5
+ MOVD s2_len+24(FP), R6
-+ MOVD R4, R8
-+ CMPBLE R4, R6, s1min
-+ MOVD R6, R8
-+s1min:
-+ CMPBEQ R8, $0, cmplengths
-+ CMP R8, $256
-+ BLE tail
-+loop:
-+ CLC $256, 0(R5), 0(R3)
-+ BGT gt
-+ BLT lt
-+ SUB $256, R8
-+ CMP R8, $256
-+ BGT loop
-+tail:
-+ SUB $1, R8
-+ EXRL $runtime·cmpbody_clc(SB), R8
-+ BGT gt
-+ BLT lt
-+cmplengths:
-+ CMP R4, R6
-+ BEQ eq
-+ BLT lt
-+ BGT gt
-+gt:
-+ MOVD $1, R7
-+ BR quit
-+lt:
-+ MOVD $-1, R7
-+ BR quit
-+eq:
-+ MOVD $0, R7
-+quit:
-+ MOVD R7, ret+32(FP)
-+ RET
++ LA ret+32(FP), R7
++ BR runtime·cmpbody(SB)
+
-+TEXT bytes·Compare(SB),NOSPLIT,$0-56
++TEXT bytes·Compare(SB),NOSPLIT|NOFRAME,$0-56
+ MOVD s1+0(FP), R3
+ MOVD s1+8(FP), R4
+ MOVD s2+24(FP), R5
+ MOVD s2+32(FP), R6
-+ MOVD R4, R8
-+ CMPBLE R4, R6, s1min
-+ MOVD R6, R8
-+s1min:
-+ CMPBEQ R8, $0, cmplengths
-+ CMP R8, $256
-+ BLE tail
-+loop:
-+ CLC $256, 0(R5), 0(R3)
-+ BGT gt
-+ BLT lt
-+ SUB $256, R8
-+ CMP R8, $256
-+ BGT loop
-+tail:
-+ SUB $1, R8
-+ EXRL $runtime·cmpbody_clc(SB), R8
-+ BGT gt
-+ BLT lt
-+cmplengths:
-+ CMP R4, R6
-+ BEQ eq
-+ BLT lt
-+ BGT gt
-+gt:
-+ MOVD $1, R7
-+ BR quit
-+lt:
-+ MOVD $-1, R7
-+ BR quit
-+eq:
-+ MOVD $0, R7
-+quit:
-+ MOVD R7, res+48(FP)
-+ RET
-+
-+TEXT runtime·cmpbody_clc(SB),NOSPLIT,$0-0
-+ CLC $1, 0(R5), 0(R3)
-+ RET
++ LA res+48(FP), R7
++ BR runtime·cmpbody(SB)
+
+// input:
+// R3 = a
-+// R5 = b
+// R4 = alen
++// R5 = b
+// R6 = blen
+// R7 = address of output word (stores -1/0/1 here)
+TEXT runtime·cmpbody(SB),NOSPLIT|NOFRAME,$0-0
++ CMPBEQ R3, R5, cmplengths
+ MOVD R4, R8
-+ CMPBGE R4, R6, 2(PC)
++ CMPBLE R4, R6, amin
+ MOVD R6, R8
++amin:
++ CMPBEQ R8, $0, cmplengths
+ CMP R8, $256
+ BLE tail
+loop:
-+ CLC $256, 0(R5), 0(R3)
++ CLC $256, 0(R3), 0(R5)
+ BGT gt
+ BLT lt
+ SUB $256, R8
@@ -23737,22 +35004,25 @@ index 0000000..861747e
+ BGT loop
+tail:
+ SUB $1, R8
-+ EXRL $runtime·cmpbody_clc(SB), R8
++ EXRL $runtime·cmpbodyclc(SB), R8
+ BGT gt
+ BLT lt
-+
++cmplengths:
+ CMP R4, R6
+ BEQ eq
+ BLT lt
-+ BGT gt
+gt:
-+ MOVD $-1, R7
++ MOVD $1, 0(R7)
+ RET
+lt:
-+ MOVD $1, R7
++ MOVD $-1, 0(R7)
+ RET
+eq:
-+ MOVD $0, R7
++ MOVD $0, 0(R7)
++ RET
++
++TEXT runtime·cmpbodyclc(SB),NOSPLIT|NOFRAME,$0-0
++ CLC $1, 0(R3), 0(R5)
+ RET
+
+// This is called from .init_array and follows the platform, not Go, ABI.
@@ -23762,13 +35032,7 @@ index 0000000..861747e
+TEXT runtime·addmoduledata(SB),NOSPLIT|NOFRAME,$0-0
+ // Save R6-R15, F0, F2, F4 and F6 in the
+ // register save area of the calling function
-+ // stmg %r6, %r15, 48(%r15)
-+ BYTE $0xeb;
-+ BYTE $0x6f;
-+ BYTE $0xf0;
-+ BYTE $0x30;
-+ BYTE $0x00;
-+ BYTE $0x24;
++ STMG R6, R15, 48(R15)
+ FMOVD F0, 128(R15)
+ FMOVD F2, 136(R15)
+ FMOVD F4, 144(R15)
@@ -23781,13 +35045,7 @@ index 0000000..861747e
+ MOVD R2, runtime·lastmoduledatap(SB)
+
+ // Restore R6-R15, F0, F2, F4 and F6
-+ // lmg %r6, %r15, 48(%r15)
-+ BYTE $0xeb;
-+ BYTE $0x6f;
-+ BYTE $0xf0;
-+ BYTE $0x30;
-+ BYTE $0x00;
-+ BYTE $0x04;
++ LMG 48(R15), R6, R15
+ FMOVD F0, 128(R15)
+ FMOVD F2, 136(R15)
+ FMOVD F4, 144(R15)
@@ -23800,10 +35058,10 @@ index 0000000..861747e
+ RET
diff --git a/src/runtime/cgo/asm_s390x.s b/src/runtime/cgo/asm_s390x.s
new file mode 100644
-index 0000000..64b2ab4
+index 0000000..dcb1e6b
--- /dev/null
+++ b/src/runtime/cgo/asm_s390x.s
-@@ -0,0 +1,56 @@
+@@ -0,0 +1,44 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
@@ -23820,13 +35078,7 @@ index 0000000..64b2ab4
+
+ // Save R6-R15, F0, F2, F4 and F6 in the
+ // register save area of the calling function
-+ // stmg %r6, %r15, 48(%r15)
-+ BYTE $0xeb;
-+ BYTE $0x6f;
-+ BYTE $0xf0;
-+ BYTE $0x30;
-+ BYTE $0x00;
-+ BYTE $0x24;
++ STMG R6, R15, 48(R15)
+ FMOVD F0, 128(R15)
+ FMOVD F2, 136(R15)
+ FMOVD F4, 144(R15)
@@ -23846,13 +35098,7 @@ index 0000000..64b2ab4
+ ADD $24, R15
+
+ // Restore R6-R15, F0, F2, F4 and F6
-+ // lmg %r6, %r15, 48(%r15)
-+ BYTE $0xeb;
-+ BYTE $0x6f;
-+ BYTE $0xf0;
-+ BYTE $0x30;
-+ BYTE $0x00;
-+ BYTE $0x04;
++ LMG 48(R15), R6, R15
+ FMOVD F0, 128(R15)
+ FMOVD F2, 136(R15)
+ FMOVD F4, 144(R15)
@@ -23984,7 +35230,7 @@ index 0000000..dc242eb
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/src/runtime/cgocall.go b/src/runtime/cgocall.go
-index 66115fd..634b6e7 100644
+index 66115fd..7d9910c 100644
--- a/src/runtime/cgocall.go
+++ b/src/runtime/cgocall.go
@@ -239,8 +239,8 @@ func cgocallbackg1() {
@@ -24007,6 +35253,79 @@ index 66115fd..634b6e7 100644
sched.sp = *(*uintptr)(unsafe.Pointer(sched.sp + sys.MinFrameSize))
case "arm64":
sched.sp = *(*uintptr)(unsafe.Pointer(sched.sp + 16))
+@@ -463,6 +463,9 @@ func cgoCheckArg(t *_type, p unsafe.Pointer, indir, top bool, msg string) {
+ if !top {
+ panic(errorString(msg))
+ }
++ if st.elem.kind&kindNoPointers != 0 {
++ return
++ }
+ for i := 0; i < s.cap; i++ {
+ cgoCheckArg(st.elem, p, true, false, msg)
+ p = add(p, st.elem.size)
+diff --git a/src/runtime/crash_cgo_test.go b/src/runtime/crash_cgo_test.go
+index d7b367f..7685582 100644
+--- a/src/runtime/crash_cgo_test.go
++++ b/src/runtime/crash_cgo_test.go
+@@ -7,10 +7,12 @@
+ package runtime_test
+
+ import (
++ "internal/testenv"
+ "os/exec"
+ "runtime"
+ "strings"
+ "testing"
++ "time"
+ )
+
+ func TestCgoCrashHandler(t *testing.T) {
+@@ -147,3 +149,32 @@ func TestEnsureDropM(t *testing.T) {
+ t.Errorf("expected %q, got %v", want, got)
+ }
+ }
++
++// Test for issue 14387.
++// Test that the program that doesn't need any cgo pointer checking
++// takes about the same amount of time with it as without it.
++func TestCgoCheckBytes(t *testing.T) {
++ // Make sure we don't count the build time as part of the run time.
++ testenv.MustHaveGoBuild(t)
++ exe, err := buildTestProg(t, "testprogcgo")
++ if err != nil {
++ t.Fatal(err)
++ }
++
++ cmd := testEnv(exec.Command(exe, "CgoCheckBytes"))
++
++ start := time.Now()
++ cmd.Run()
++ d1 := time.Since(start)
++
++ cmd = testEnv(exec.Command(exe, "CgoCheckBytes"))
++ cmd.Env = append(cmd.Env, "GODEBUG=cgocheck=0")
++
++ start = time.Now()
++ cmd.Run()
++ d2 := time.Since(start)
++
++ if d2*10 < d1 {
++ t.Errorf("cgo check too slow: got %v, expected at most %v", d1, d2*10)
++ }
++}
+diff --git a/src/runtime/debug/stack_test.go b/src/runtime/debug/stack_test.go
+index f544372..9376e82 100644
+--- a/src/runtime/debug/stack_test.go
++++ b/src/runtime/debug/stack_test.go
+@@ -59,7 +59,7 @@ func TestStack(t *testing.T) {
+ }
+
+ func check(t *testing.T, line, has string) {
+- if strings.Index(line, has) < 0 {
++ if !strings.Contains(line, has) {
+ t.Errorf("expected %q in %q", has, line)
+ }
+ }
diff --git a/src/runtime/defs_linux_s390x.go b/src/runtime/defs_linux_s390x.go
new file mode 100644
index 0000000..893a31c
@@ -25276,10 +36595,10 @@ index 0000000..0b09332
+}
diff --git a/src/runtime/sys_linux_s390x.s b/src/runtime/sys_linux_s390x.s
new file mode 100644
-index 0000000..9431fc2
+index 0000000..a4a4693
--- /dev/null
+++ b/src/runtime/sys_linux_s390x.s
-@@ -0,0 +1,437 @@
+@@ -0,0 +1,440 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
@@ -25528,17 +36847,17 @@ index 0000000..9431fc2
+ BL R11
+ RET
+
++// func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) unsafe.Pointer
+TEXT runtime·mmap(SB),NOSPLIT,$48-40
+ MOVD addr+0(FP), R2
+ MOVD n+8(FP), R3
+ MOVW prot+16(FP), R4
+ MOVW flags+20(FP), R5
+ MOVW fd+24(FP), R6
-+ MOVW off+28(FP), R7
++ MOVWZ off+28(FP), R7
+
+ // s390x uses old_mmap, so the arguments need to be placed into
+ // a struct and a pointer to the struct passed to mmap.
-+ // TODO Offset should NOT be sign extended (it is a uint32).
+ MOVD R2, addr-48(SP)
+ MOVD R3, n-40(SP)
+ MOVD R4, prot-32(SP)
@@ -25549,6 +36868,9 @@ index 0000000..9431fc2
+ MOVD $addr-48(SP), R2
+ MOVW $SYS_mmap, R1
+ SYSCALL
++ MOVD $-4095, R3
++ CMPUBLT R2, R3, 2(PC)
++ NEG R2
+ MOVD R2, ret+32(FP)
+ RET
+
@@ -25771,6 +37093,42 @@ index 0000000..106d7ea
+ print("runtime: pc=", hex(buf.pc), " ", hex(inst), "\n")
+ throw("runtime: misuse of rewindmorestack")
+}
+diff --git a/src/runtime/testdata/testprogcgo/cgo.go b/src/runtime/testdata/testprogcgo/cgo.go
+index cf1af82..5d2550d 100644
+--- a/src/runtime/testdata/testprogcgo/cgo.go
++++ b/src/runtime/testdata/testprogcgo/cgo.go
+@@ -6,17 +6,20 @@ package main
+
+ /*
+ void foo1(void) {}
++void foo2(void* p) {}
+ */
+ import "C"
+ import (
+ "fmt"
+ "runtime"
+ "time"
++ "unsafe"
+ )
+
+ func init() {
+ register("CgoSignalDeadlock", CgoSignalDeadlock)
+ register("CgoTraceback", CgoTraceback)
++ register("CgoCheckBytes", CgoCheckBytes)
+ }
+
+ func CgoSignalDeadlock() {
+@@ -78,3 +81,10 @@ func CgoTraceback() {
+ runtime.Stack(buf, true)
+ fmt.Printf("OK\n")
+ }
++
++func CgoCheckBytes() {
++ b := make([]byte, 1e6)
++ for i := 0; i < 1e3; i++ {
++ C.foo2(unsafe.Pointer(&b[0]))
++ }
++}
diff --git a/src/runtime/tls_s390x.s b/src/runtime/tls_s390x.s
new file mode 100644
index 0000000..03bfc50
@@ -25841,6 +37199,19 @@ index d3d6c70..602fd67 100644
package runtime
+diff --git a/src/sort/sort.go b/src/sort/sort.go
+index ac8f4a6..5eb45c6 100644
+--- a/src/sort/sort.go
++++ b/src/sort/sort.go
+@@ -335,7 +335,7 @@ func StringsAreSorted(a []string) bool { return IsSorted(StringSlice(a)) }
+ // unstable or rely on enough different elements in each step to encode the
+ // performed block rearrangements. See also "In-Place Merging Algorithms",
+ // Denham Coates-Evely, Department of Computer Science, Kings College,
+-// January 2004 and the reverences in there.
++// January 2004 and the references in there.
+ // - Often "optimal" algorithms are optimal in the number of assignments
+ // but Interface has only Swap as operation.
+
diff --git a/src/sync/atomic/asm_s390x.s b/src/sync/atomic/asm_s390x.s
new file mode 100644
index 0000000..a96cce3
@@ -26218,12 +37589,39 @@ index 85fab4f..1d40092 100755
nacl_386)
mkerrors=""
mksyscall="./mksyscall.pl -l32 -nacl"
+diff --git a/src/syscall/mksyscall.pl b/src/syscall/mksyscall.pl
+index 96437fe..6ee7c3c 100755
+--- a/src/syscall/mksyscall.pl
++++ b/src/syscall/mksyscall.pl
+@@ -100,7 +100,7 @@ while(<>) {
+ # Line must be of the form
+ # func Open(path string, mode int, perm int) (fd int, errno error)
+ # Split into name, in params, out params.
+- if(!/^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*((?i)SYS_[A-Z0-9_]+))?$/) {
++ if(!/^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*((?i)_?SYS_[A-Z0-9_]+))?$/) {
+ print STDERR "$ARGV:$.: malformed //sys declaration\n";
+ $errors = 1;
+ next;
+diff --git a/src/syscall/syscall_linux.go b/src/syscall/syscall_linux.go
+index 2875067..b5e33bf 100644
+--- a/src/syscall/syscall_linux.go
++++ b/src/syscall/syscall_linux.go
+@@ -301,7 +301,8 @@ func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) {
+ }
+ sa.raw.Family = AF_UNIX
+ for i := 0; i < n; i++ {
+- sa.raw.Path[i] = int8(name[i])
++ bp := (*byte)(unsafe.Pointer(&sa.raw.Path[i]))
++ *bp = name[i]
+ }
+ // length is family (uint16), name, NUL.
+ sl := _Socklen(2)
diff --git a/src/syscall/syscall_linux_s390x.go b/src/syscall/syscall_linux_s390x.go
new file mode 100644
-index 0000000..20a1a45
+index 0000000..4fc9c3f
--- /dev/null
+++ b/src/syscall/syscall_linux_s390x.go
-@@ -0,0 +1,296 @@
+@@ -0,0 +1,299 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
@@ -26232,7 +37630,10 @@ index 0000000..20a1a45
+
+import "unsafe"
+
-+const _SYS_dup = SYS_DUP2
++const (
++ _SYS_dup = SYS_DUP2
++ _SYS_getdents = SYS_GETDENTS64
++)
+
+//sys Dup2(oldfd int, newfd int) (err error)
+//sys Fchown(fd int, uid int, gid int) (err error)
@@ -26562,10 +37963,10 @@ index cff4069..6d197d8 100644
// Misc
diff --git a/src/syscall/zerrors_linux_s390x.go b/src/syscall/zerrors_linux_s390x.go
new file mode 100644
-index 0000000..4e25255
+index 0000000..547419f
--- /dev/null
+++ b/src/syscall/zerrors_linux_s390x.go
-@@ -0,0 +1,1869 @@
+@@ -0,0 +1,1893 @@
+// mkerrors.sh -m64
+// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
+
@@ -26600,7 +38001,7 @@ index 0000000..4e25255
+ AF_KEY = 0xf
+ AF_LLC = 0x1a
+ AF_LOCAL = 0x1
-+ AF_MAX = 0x28
++ AF_MAX = 0x29
+ AF_NETBEUI = 0xd
+ AF_NETLINK = 0x10
+ AF_NETROM = 0x6
@@ -26617,6 +38018,7 @@ index 0000000..4e25255
+ AF_TIPC = 0x1e
+ AF_UNIX = 0x1
+ AF_UNSPEC = 0x0
++ AF_VSOCK = 0x28
+ AF_WANPIPE = 0x19
+ AF_X25 = 0x9
+ ARPHRD_ADAPT = 0x108
@@ -26833,12 +38235,10 @@ index 0000000..4e25255
+ EPOLL_CTL_ADD = 0x1
+ EPOLL_CTL_DEL = 0x2
+ EPOLL_CTL_MOD = 0x3
-+ EPOLL_NONBLOCK = 0x800
+ ETH_P_1588 = 0x88f7
+ ETH_P_8021AD = 0x88a8
+ ETH_P_8021AH = 0x88e7
+ ETH_P_8021Q = 0x8100
-+ ETH_P_80221 = 0x8917
+ ETH_P_802_2 = 0x4
+ ETH_P_802_3 = 0x1
+ ETH_P_802_3_MIN = 0x600
@@ -26958,15 +38358,13 @@ index 0000000..4e25255
+ IFA_F_DADFAILED = 0x8
+ IFA_F_DEPRECATED = 0x20
+ IFA_F_HOMEADDRESS = 0x10
-+ IFA_F_MANAGETEMPADDR = 0x100
+ IFA_F_NODAD = 0x2
-+ IFA_F_NOPREFIXROUTE = 0x200
+ IFA_F_OPTIMISTIC = 0x4
+ IFA_F_PERMANENT = 0x80
+ IFA_F_SECONDARY = 0x1
+ IFA_F_TEMPORARY = 0x1
+ IFA_F_TENTATIVE = 0x40
-+ IFA_MAX = 0x8
++ IFA_MAX = 0x7
+ IFF_802_1Q_VLAN = 0x1
+ IFF_ALLMULTI = 0x200
+ IFF_ATTACH_QUEUE = 0x200
@@ -26994,10 +38392,12 @@ index 0000000..4e25255
+ IFF_MULTICAST = 0x1000
+ IFF_MULTI_QUEUE = 0x100
+ IFF_NOARP = 0x80
++ IFF_NOFILTER = 0x1000
+ IFF_NOTRAILERS = 0x20
+ IFF_NO_PI = 0x1000
+ IFF_ONE_QUEUE = 0x2000
+ IFF_OVS_DATAPATH = 0x8000
++ IFF_PERSIST = 0x800
+ IFF_POINTOPOINT = 0x10
+ IFF_PORTSEL = 0x2000
+ IFF_PROMISC = 0x100
@@ -27063,6 +38463,7 @@ index 0000000..4e25255
+ IN_Q_OVERFLOW = 0x4000
+ IN_UNMOUNT = 0x2000
+ IPPROTO_AH = 0x33
++ IPPROTO_BEETPH = 0x5e
+ IPPROTO_COMP = 0x6c
+ IPPROTO_DCCP = 0x21
+ IPPROTO_DSTOPTS = 0x3c
@@ -27079,6 +38480,7 @@ index 0000000..4e25255
+ IPPROTO_IP = 0x0
+ IPPROTO_IPIP = 0x4
+ IPPROTO_IPV6 = 0x29
++ IPPROTO_MH = 0x87
+ IPPROTO_MTP = 0x5c
+ IPPROTO_NONE = 0x3b
+ IPPROTO_PIM = 0x67
@@ -27231,8 +38633,9 @@ index 0000000..4e25255
+ MAP_FILE = 0x0
+ MAP_FIXED = 0x10
+ MAP_GROWSDOWN = 0x100
-+ MAP_GROWSUP = 0x200
+ MAP_HUGETLB = 0x40000
++ MAP_HUGE_MASK = 0x3f
++ MAP_HUGE_SHIFT = 0x1a
+ MAP_LOCKED = 0x2000
+ MAP_NONBLOCK = 0x10000
+ MAP_NORESERVE = 0x4000
@@ -27380,6 +38783,7 @@ index 0000000..4e25255
+ O_RDWR = 0x2
+ O_RSYNC = 0x101000
+ O_SYNC = 0x101000
++ O_TMPFILE = 0x410000
+ O_TRUNC = 0x200
+ O_WRONLY = 0x1
+ PACKET_ADD_MEMBERSHIP = 0x1
@@ -27467,7 +38871,6 @@ index 0000000..4e25255
+ PR_GET_PDEATHSIG = 0x2
+ PR_GET_SECCOMP = 0x15
+ PR_GET_SECUREBITS = 0x1b
-+ PR_GET_THP_DISABLE = 0x2a
+ PR_GET_TID_ADDRESS = 0x28
+ PR_GET_TIMERSLACK = 0x1e
+ PR_GET_TIMING = 0xd
@@ -27507,7 +38910,6 @@ index 0000000..4e25255
+ PR_SET_PTRACER_ANY = -0x1
+ PR_SET_SECCOMP = 0x16
+ PR_SET_SECUREBITS = 0x1c
-+ PR_SET_THP_DISABLE = 0x29
+ PR_SET_TIMERSLACK = 0x1d
+ PR_SET_TIMING = 0xe
+ PR_SET_TSC = 0x1a
@@ -27537,6 +38939,7 @@ index 0000000..4e25255
+ PTRACE_GETREGS = 0xc
+ PTRACE_GETREGSET = 0x4204
+ PTRACE_GETSIGINFO = 0x4202
++ PTRACE_GETSIGMASK = 0x420a
+ PTRACE_GET_LAST_BREAK = 0x5006
+ PTRACE_INTERRUPT = 0x4207
+ PTRACE_KILL = 0x8
@@ -27574,8 +38977,10 @@ index 0000000..4e25255
+ PTRACE_SETREGS = 0xd
+ PTRACE_SETREGSET = 0x4205
+ PTRACE_SETSIGINFO = 0x4203
++ PTRACE_SETSIGMASK = 0x420b
+ PTRACE_SINGLESTEP = 0x9
+ PTRACE_SYSCALL = 0x18
++ PTRACE_TE_ABORT_RAND = 0x5011
+ PTRACE_TRACEME = 0x0
+ PT_ACR0 = 0x90
+ PT_ACR1 = 0x94
@@ -27654,7 +39059,7 @@ index 0000000..4e25255
+ RTAX_INITCWND = 0xb
+ RTAX_INITRWND = 0xe
+ RTAX_LOCK = 0x1
-+ RTAX_MAX = 0x17
++ RTAX_MAX = 0xf
+ RTAX_MTU = 0x2
+ RTAX_QUICKACK = 0xf
+ RTAX_REORDERING = 0x9
@@ -27875,7 +39280,6 @@ index 0000000..4e25255
+ SO_ACCEPTCONN = 0x1e
+ SO_ATTACH_FILTER = 0x1a
+ SO_BINDTODEVICE = 0x19
-+ SO_BPF_EXTENSIONS = 0x30
+ SO_BROADCAST = 0x6
+ SO_BSDCOMPAT = 0xe
+ SO_BUSY_POLL = 0x2e
@@ -27952,8 +39356,15 @@ index 0000000..4e25255
+ TCIOFLUSH = 0x2
+ TCOFLUSH = 0x1
+ TCP_CONGESTION = 0xd
++ TCP_COOKIE_IN_ALWAYS = 0x1
++ TCP_COOKIE_MAX = 0x10
++ TCP_COOKIE_MIN = 0x8
++ TCP_COOKIE_OUT_NEVER = 0x2
++ TCP_COOKIE_PAIR_SIZE = 0x20
++ TCP_COOKIE_TRANSACTIONS = 0xf
+ TCP_CORK = 0x3
+ TCP_DEFER_ACCEPT = 0x9
++ TCP_FASTOPEN = 0x17
+ TCP_INFO = 0xb
+ TCP_KEEPCNT = 0x6
+ TCP_KEEPIDLE = 0x4
@@ -27965,9 +39376,21 @@ index 0000000..4e25255
+ TCP_MD5SIG = 0xe
+ TCP_MD5SIG_MAXKEYLEN = 0x50
+ TCP_MSS = 0x200
++ TCP_MSS_DEFAULT = 0x218
++ TCP_MSS_DESIRED = 0x4c4
+ TCP_NODELAY = 0x1
++ TCP_QUEUE_SEQ = 0x15
+ TCP_QUICKACK = 0xc
++ TCP_REPAIR = 0x13
++ TCP_REPAIR_OPTIONS = 0x16
++ TCP_REPAIR_QUEUE = 0x14
+ TCP_SYNCNT = 0x7
++ TCP_S_DATA_IN = 0x4
++ TCP_S_DATA_OUT = 0x8
++ TCP_THIN_DUPACK = 0x11
++ TCP_THIN_LINEAR_TIMEOUTS = 0x10
++ TCP_TIMESTAMP = 0x18
++ TCP_USER_TIMEOUT = 0x12
+ TCP_WINDOW_CLAMP = 0xa
+ TCSAFLUSH = 0x2
+ TIOCCBRK = 0x5428
@@ -28042,12 +39465,14 @@ index 0000000..4e25255
+ TUNATTACHFILTER = 0x401054d5
+ TUNDETACHFILTER = 0x401054d6
+ TUNGETFEATURES = 0x800454cf
++ TUNGETFILTER = 0x801054db
+ TUNGETIFF = 0x800454d2
+ TUNGETSNDBUF = 0x800454d3
+ TUNGETVNETHDRSZ = 0x800454d7
+ TUNSETDEBUG = 0x400454c9
+ TUNSETGROUP = 0x400454ce
+ TUNSETIFF = 0x400454ca
++ TUNSETIFINDEX = 0x400454da
+ TUNSETLINK = 0x400454cd
+ TUNSETNOCSUM = 0x400454c8
+ TUNSETOFFLOAD = 0x400454d0
@@ -28437,7 +39862,7 @@ index 0000000..4e25255
+}
diff --git a/src/syscall/zsyscall_linux_s390x.go b/src/syscall/zsyscall_linux_s390x.go
new file mode 100644
-index 0000000..d103c57
+index 0000000..e5b941c
--- /dev/null
+++ b/src/syscall/zsyscall_linux_s390x.go
@@ -0,0 +1,1578 @@
@@ -28948,7 +40373,7 @@ index 0000000..d103c57
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
-+ r0, _, e1 := Syscall(SYS_GETDENTS64, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
++ r0, _, e1 := Syscall(_SYS_getdents, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
+ n = int(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
@@ -30320,10 +41745,10 @@ index 0000000..90e6b2f
+)
diff --git a/src/syscall/ztypes_linux_s390x.go b/src/syscall/ztypes_linux_s390x.go
new file mode 100644
-index 0000000..87b86e2
+index 0000000..e994c58
--- /dev/null
+++ b/src/syscall/ztypes_linux_s390x.go
-@@ -0,0 +1,623 @@
+@@ -0,0 +1,621 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs types_linux.go
+
@@ -30425,21 +41850,21 @@ index 0000000..87b86e2
+type _Gid_t uint32
+
+type Stat_t struct {
-+ Dev uint64
-+ Ino uint64
-+ Nlink uint64
-+ Mode uint32
-+ Uid uint32
-+ Gid uint32
-+ Pad0 int32
-+ Rdev uint64
-+ Size int64
-+ Atim Timespec
-+ Mtim Timespec
-+ Ctim Timespec
-+ Blksize int64
-+ Blocks int64
-+ X__unused [3]int64
++ Dev uint64
++ Ino uint64
++ Nlink uint64
++ Mode uint32
++ Uid uint32
++ Gid uint32
++ Pad0 int32
++ Rdev uint64
++ Size int64
++ Atim Timespec
++ Mtim Timespec
++ Ctim Timespec
++ Blksize int64
++ Blocks int64
++ X__glibc_reserved [3]int64
+}
+
+type Statfs_t struct {
@@ -30498,7 +41923,7 @@ index 0000000..87b86e2
+
+type RawSockaddrUnix struct {
+ Family uint16
-+ Path [108]int8
++ Path [108]uint8
+}
+
+type RawSockaddrLinklayer struct {
@@ -30569,10 +41994,9 @@ index 0000000..87b86e2
+}
+
+type Cmsghdr struct {
-+ Len uint64
-+ Level int32
-+ Type int32
-+ X__cmsg_data [0]uint8
++ Len uint64
++ Level int32
++ Type int32
+}
+
+type Inet4Pktinfo struct {
@@ -30836,7 +42260,6 @@ index 0000000..87b86e2
+ Mask uint32
+ Cookie uint32
+ Len uint32
-+ Name [0]uint8
+}
+
+const SizeofInotifyEvent = 0x10
@@ -30947,6 +42370,108 @@ index 0000000..87b86e2
+ TCSETS = 0x5402
+ XCASE = 0x4
+)
+diff --git a/src/text/scanner/scanner.go b/src/text/scanner/scanner.go
+index 0155800..dd87850 100644
+--- a/src/text/scanner/scanner.go
++++ b/src/text/scanner/scanner.go
+@@ -333,7 +333,7 @@ func (s *Scanner) error(msg string) {
+ if !pos.IsValid() {
+ pos = s.Pos()
+ }
+- fmt.Fprintf(os.Stderr, "%s: %s\n", pos, msg)
++ fmt.Fprintf(os.Stderr, "text/scanner: %s: %s\n", pos, msg)
+ }
+
+ func (s *Scanner) isIdentRune(ch rune, i int) bool {
+diff --git a/src/text/template/exec.go b/src/text/template/exec.go
+index efe1817..5ea45a4 100644
+--- a/src/text/template/exec.go
++++ b/src/text/template/exec.go
+@@ -446,7 +446,7 @@ func (s *state) idealConstant(constant *parse.NumberNode) reflect.Value {
+ switch {
+ case constant.IsComplex:
+ return reflect.ValueOf(constant.Complex128) // incontrovertible.
+- case constant.IsFloat && !isHexConstant(constant.Text) && strings.IndexAny(constant.Text, ".eE") >= 0:
++ case constant.IsFloat && !isHexConstant(constant.Text) && strings.ContainsAny(constant.Text, ".eE"):
+ return reflect.ValueOf(constant.Float64)
+ case constant.IsInt:
+ n := int(constant.Int64)
+diff --git a/src/text/template/funcs.go b/src/text/template/funcs.go
+index 49e9e74..58b8ea3 100644
+--- a/src/text/template/funcs.go
++++ b/src/text/template/funcs.go
+@@ -515,7 +515,7 @@ func HTMLEscape(w io.Writer, b []byte) {
+ // HTMLEscapeString returns the escaped HTML equivalent of the plain text data s.
+ func HTMLEscapeString(s string) string {
+ // Avoid allocation if we can.
+- if strings.IndexAny(s, `'"&<>`) < 0 {
++ if !strings.ContainsAny(s, `'"&<>`) {
+ return s
+ }
+ var b bytes.Buffer
+diff --git a/src/text/template/parse/lex.go b/src/text/template/parse/lex.go
+index ea93e05..079c0ea 100644
+--- a/src/text/template/parse/lex.go
++++ b/src/text/template/parse/lex.go
+@@ -155,7 +155,7 @@ func (l *lexer) ignore() {
+
+ // accept consumes the next rune if it's from the valid set.
+ func (l *lexer) accept(valid string) bool {
+- if strings.IndexRune(valid, l.next()) >= 0 {
++ if strings.ContainsRune(valid, l.next()) {
+ return true
+ }
+ l.backup()
+@@ -164,7 +164,7 @@ func (l *lexer) accept(valid string) bool {
+
+ // acceptRun consumes a run of runes from the valid set.
+ func (l *lexer) acceptRun(valid string) {
+- for strings.IndexRune(valid, l.next()) >= 0 {
++ for strings.ContainsRune(valid, l.next()) {
+ }
+ l.backup()
+ }
+diff --git a/src/time/format_test.go b/src/time/format_test.go
+index af950a7..8c47dbc 100644
+--- a/src/time/format_test.go
++++ b/src/time/format_test.go
+@@ -447,7 +447,7 @@ func TestParseErrors(t *testing.T) {
+ _, err := Parse(test.format, test.value)
+ if err == nil {
+ t.Errorf("expected error for %q %q", test.format, test.value)
+- } else if strings.Index(err.Error(), test.expect) < 0 {
++ } else if !strings.Contains(err.Error(), test.expect) {
+ t.Errorf("expected error with %q for %q %q; got %s", test.expect, test.format, test.value, err)
+ }
+ }
+diff --git a/test/escape_iface.go b/test/escape_iface.go
+index 2b1144a..9149fa1 100644
+--- a/test/escape_iface.go
++++ b/test/escape_iface.go
+@@ -225,3 +225,23 @@ func dotTypeEscape() *T2 { // #11931
+ T1: *(x.(*T1)), // ERROR "&T2 literal escapes to heap"
+ }
+ }
++
++func dotTypeEscape2() { // #13805
++ {
++ i := 0
++ var v int
++ var x interface{} = i // ERROR "i does not escape"
++ *(&v) = x.(int) // ERROR "&v does not escape"
++ }
++ {
++ i := 0
++ var x interface{} = i // ERROR "i does not escape"
++ sink = x.(int) // ERROR "x.\(int\) escapes to heap"
++
++ }
++ {
++ i := 0 // ERROR "moved to heap: i"
++ var x interface{} = &i // ERROR "&i escapes to heap"
++ sink = x.(*int) // ERROR "x.\(\*int\) escapes to heap"
++ }
++}
diff --git a/test/fixedbugs/issue11656.go b/test/fixedbugs/issue11656.go
index 565e796..08c143e 100644
--- a/test/fixedbugs/issue11656.go
@@ -30973,6 +42498,19 @@ index 62dfb72..a008e3e 100644
panic("init1")
}
}
+diff --git a/test/linkx_run.go b/test/linkx_run.go
+index a6c7c67..440271a 100644
+--- a/test/linkx_run.go
++++ b/test/linkx_run.go
+@@ -18,7 +18,7 @@ import (
+ )
+
+ func main() {
+- test(" ") // old deprecated syntax
++ // test(" ") // old deprecated & removed syntax
+ test("=") // new syntax
+ }
+
diff --git a/test/nilptr3.go b/test/nilptr3.go
index 6c8aab3..7d579fd 100644
--- a/test/nilptr3.go
@@ -31001,6 +42539,3 @@ index 3c4ae10..189a320 100644
default:
fmt.Fprintf(&buf, "#define REGISTER AX\n")
}
---
-2.5.0
-
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-golang/golang.git
More information about the pkg-golang-commits
mailing list